2009-05-13 22 views

Odpowiedz

5

to będzie działać na serwerze sql 2005 i up:

select * from INFORMATION_SCHEMA.COLUMNS 
where TABLE_Name='YourTableName' 
order by ORDINAL_POSITION 
+2

, ale pracuję w programie Access, aw dostępie to nie działa – Gold

+1

@Gold, dodaj "dostęp" do pytania! –

+0

To nie działa w dostępie. Czy możesz wyjaśnić, czym jest INFORMATION_SCHEMA? –

0

zależności od silnika DB swoją użyciu można łatwo kwerendy tabele systemowe dB dla tej informacji

za dostęp nie mogę znaleźć odpowiedzi wiem, że can see the sys tables w dostępie i stamtąd można próbować określić, gdzie ta informacja jest tylko nie jestem naprawdę pewna, jak wykonać tę część. próbowałem użyć przykładu, ale dostałem gdzie teraz

+1

MSysObjects zawiera listę tabel, niestety nie ma odpowiednika dla pól. –

2

Czy pytasz, w jaki sposób można uzyskać nazwy kolumn tabeli w bazie danych?

Jeśli tak, to całkowicie zależy od używanego serwera bazy danych.

W SQL 2005 można wybrać z INFORMATION_SCHEMA.Columns View

SELECT * 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = 'MyTable' 

w SQL 2000 można dołączyć do syscolumns sysobjects aby uzyskać informacje

SELECT  
    dbo.sysobjects.name As TableName 
    , dbo.syscolumns.name AS FieldName 
FROM 
    dbo.sysobjects 
    INNER JOIN dbo.syscolumns 
     ON dbo.sysobjects.id = dbo.syscolumns.id 
WHERE 
    dbo.sysobjects.name = 'MyTable' 
+0

Jak twoja odpowiedź ma zastosowanie do Access/Jet? –

+0

-1 On pyta o MS Access. –

+1

Przepraszam, odbieram moje -1, pierwotne pytanie nie było jasne w tej kwestii. –

4

uruchomić tę kwerendę:

select top 1 * 
From foo 

a następnie przejdź pola listy (i zwróconych wartości) w zestawie wyników, aby uzyskać nazwy pól.

+0

Jeśli potrzebujesz tylko nazw kolumn *, to szybkie i brudne podejście jest w porządku IMO. Zauważ, że możesz dodać WHERE 0 = 1 (lub podobne), aby upewnić się, że żadne dane nie są zwracane. – onedaywhen

+0

To nie działa, jeśli masz zdefiniowane napisy. Zamiast tego pokazuje podpis. – jpmc26

1

Skorzystaj z klas automatyzacji DAO. Być może masz już bibliotekę współdziałania dla niej w instalacji programu Visual Studio. Jeśli nie, łatwo jest go stworzyć; po prostu dodaj odwołanie do biblioteki DAO COM.

using dao; 
... 
DBEngineClass dbengine = new DBEngineClass(); 
dbengine.OpenDatabase(path, null, null, null); 
Database database = dbengine.Workspaces[0].Databases[0]; 
List<string> fieldnames = new List<string>(); 
TableDef tdf = database.TableDefs[tableName]; 
for (int i = 0; i < tdf.Fields.Count; i++) 
{ 
    fieldnames.Add(tdf.Fields[i].Name); 
} 
database.Close(); 
dbengine.Workspaces[0].Close(); 

To jest tak łatwe, jak odpytywanie tabeli systemowej (co ja okazało się być problematyczne w programie Access), można uzyskać wiele dodatkowych informacji w ten sposób.

EDIT: Mam zmodyfikowany kod z co napisałem wczoraj, którą właśnie tłumaczone z VB.NET, a który zaginął kilka sztuk. Przepisałem go i przetestowałem w C# w VS2008.

+0

Z katalogu C# funkcje katalogu ADO mogą być łatwiejsze. –

+1

IIRC wywołania OpenSchema, aby uzyskać WIDOK SCHEMATÓW INFORMACYJNYCH nie są proste dla C# i mogą nie być warte tylko dla nazw kolumn. – onedaywhen

8

Zastosowanie IDataReader.GetSchemaTable()

Oto rzeczywisty przykład, który ma dostęp do schematu tabeli i wydruki to zwykły i XML (po prostu zobaczyć, jakie informacje można uzyskać):

class AccessTableSchemaTest 
{ 
    public static DbConnection GetConnection() 
    { 
     return new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=..\\Test.mdb"); 
    } 

    static void Main(string[] args) 
    { 
     using (DbConnection conn = GetConnection()) 
     { 
      conn.Open(); 

      DbCommand command = conn.CreateCommand(); 
      // (1) we're not interested in any data 
      command.CommandText = "select * from Test where 1 = 0"; 
      command.CommandType = CommandType.Text; 

      DbDataReader reader = command.ExecuteReader(); 
      // (2) get the schema of the result set 
      DataTable schemaTable = reader.GetSchemaTable(); 

      conn.Close(); 
     } 

     PrintSchemaPlain(schemaTable); 

     Console.WriteLine(new string('-', 80)); 

     PrintSchemaAsXml(schemaTable); 

     Console.Read(); 
    } 

    private static void PrintSchemaPlain(DataTable schemaTable) 
    { 
     foreach (DataRow row in schemaTable.Rows) 
     { 
      Console.WriteLine("{0}, {1}, {2}", 
       row.Field<string>("ColumnName"), 
       row.Field<Type>("DataType"), 
       row.Field<int>("ColumnSize")); 
     } 
    } 

    private static void PrintSchemaAsXml(DataTable schemaTable) 
    { 
     StringWriter stringWriter = new StringWriter(); 
     schemaTable.WriteXml(stringWriter); 
     Console.WriteLine(stringWriter.ToString()); 
    } 
} 

ciekawe miejsca:

  1. Nie zwracaj żadnych danych, podając klauzulę where, która zawsze jest fałszywa. Oczywiście dotyczy to tylko osób, które nie są zainteresowane danymi :-).
  2. Użyj IDataReader.GetSchemaTable(), aby uzyskać DataTable ze szczegółowymi informacjami o rzeczywistej tabeli.

Na moim stole testowym wyjście było:

ID, System.Int32, 4 
Field1, System.String, 50 
Field2, System.Int32, 4 
Field3, System.DateTime, 8 
-------------------------------------------------------------------------------- 
<DocumentElement> 
    <SchemaTable> 
    <ColumnName>ID</ColumnName> 
    <ColumnOrdinal>0</ColumnOrdinal> 
    <ColumnSize>4</ColumnSize> 
    <NumericPrecision>10</NumericPrecision> 
    <NumericScale>255</NumericScale> 
    <DataType>System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</DataType> 
    <ProviderType>3</ProviderType> 
    <IsLong>false</IsLong> 
    <AllowDBNull>true</AllowDBNull> 
    <IsReadOnly>false</IsReadOnly> 
    <IsRowVersion>false</IsRowVersion> 
    <IsUnique>false</IsUnique> 
    <IsKey>false</IsKey> 
    <IsAutoIncrement>false</IsAutoIncrement> 
    </SchemaTable> 
    [...] 
</DocumentElement> 
+0

Czy "conn.Close()" nie jest nadmiarowe, ponieważ połączenie jest tworzone wewnątrz konstruktu "using", który zamknie połączenie, gdy wykonanie zostanie mimo wszystko wykonane? –

0

dla Microsoft SQL w C# można wykonać następujące czynności:

Dictionary<string, int> map = 
(from DataRow row in Schema.Rows 
let columnName = (string)row["ColumnName"] 
    select columnName) 
.Distinct(StringComparer.InvariantCulture) 
.Select((columnName, index) => new { Key = columnName, Value = index }) 
.ToDictionary(pair => pair.Key, pair => pair.Value); 

ten sposób tworzy mapę nazwy kolumny w jej indeks, którego można używać w następujący sposób:

internal sealed class ColumnToIndexMap 
{ 
    private const string NameOfColumn = "ColumnName"; 
    private DataTable Schema { get; set; } 
    private Dictionary<string, int> Map { get; set; } 

    public ColumnToIndexMap(DataTable schema) 
    { 
     if (schema == null) throw new ArgumentNullException("schema"); 
     Schema = schema; 

     Map = (from DataRow row in Schema.Rows 
       let columnName = (string)row[NameOfColumn] 
       select columnName) 
       .Distinct(StringComparer.InvariantCulture) 
       .Select((columnName, index) => new { Key = columnName, Value = index }) 
       .ToDictionary(pair => pair.Key, pair => pair.Value); 
    } 

    int this[string name] 
    { 
     get { return Map[name]; } 
    } 

    string this[int index] 
    { 
     get { return Schema.Rows[index][NameOfColumn].ToString(); } 
    } 
} 
0

Mam szczęście z właściwością GetSchema produktu OleDb.Connection:

Klasa zapewniająca dane kolumn. Zwraca WSZYSTKIE kolumny w bazie danych. Otrzymany DataTable można następnie przesączono przez nazwy kolumn odpowiadających (głównie) do tych w standardowych INFORMATION_SCHEMA (co MS dostępu nie przewiduje USA):

class JetMetaData 
    { 
     /// <summary> 
     /// Returns a datatable containing MetaData for all user-columns 
     /// in the current JET Database. 
     /// </summary> 
     /// <returns></returns> 
     public static DataTable AllColumns(String ConnectionString) 
     { 
      DataTable dt; 

      using (OleDbConnection cn = new OleDbConnection(ConnectionString)) 
      { 
       cn.Open(); 
       dt = cn.GetSchema("Columns"); 
       cn.Close(); 
      } 
      return dt; 
     } 

    } 

Następnie Spożywanie tej klasy A a surowe i niezbyt eleganckim przykładem i filtrowanie na TABLE_NAME:

private void Form1_Load(object sender, EventArgs e) 
    { 
     DataTable dt = JetMetaData.AllColumns("", Properties.Settings.Default.JetConnection); 
     String RowFilter = "TABLE_NAME = 'YourTableName'"; 
     DataView drv = dt.DefaultView; 
     drv.RowFilter = RowFilter; 

     DataGridView dgv = this.dataGridView1; 

     dgv.DataSource = drv; 

    } 

pamiętać, że nie udawać, że to wszystko jest dobrze chociaż się kod. To tylko przykład. Ale użyłem czegoś takiego od wielu okazjach, w rzeczywistości nawet stworzyła aplikację do skryptu z całej bazy danych MS Access (contraints i wszystko) przy użyciu podobnych metod.

Podczas gdy widziałem innych w tym wątku, wspominają o schemacie, wydaje się, że niektóre implementacje były zbyt skomplikowane. . .

Nadzieję, że pomaga!

1

Ten kod wypisze wszystkie nazwy kolumny tabeli jako klasa z getter własności wszystkich nazw kolumn, które mogą być następnie wykorzystane w kodzie

declare @TableName sysname = '<EnterTableName>' 
    declare @Result varchar(max) = 'public class ' + @TableName + ' 
    {' 

    select @Result = @Result + ' 
     public static string ' + ColumnName + ' { get { return "'+ColumnName+'"; } } 
    ' 
    from 
    (
     select 
      replace(col.name, ' ', '_') ColumnName, 
      column_id ColumnId 
     from sys.columns col 
      join sys.types typ on 
       col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id 
     where object_id = object_id(@TableName) 
    ) t 
    order by ColumnId 

    set @Result = @Result + ' 
    }' 

    print @Result 

Wyjście c#:

public class tblPracticeTestSections 
{ 
    public static string column1 { get { return "column1"; } } 

    public static string column2{ get { return "column2"; } } 

    public static string column3{ get { return "column3"; } } 

    public static string column4{ get { return "column4"; } } 

} 
Powiązane problemy