2009-05-13 24 views

Antwort

5

diese auf SQL Server arbeiten 2005 und up:

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

aber ich arbeite in Access, und im Zugriff ist es nicht Arbeit – Gold

+1

@Gold, fügen Sie "Zugriff" Tag zu Frage! –

+0

Dies funktioniert nicht im Zugriff. Können Sie erklären, was INFORMATION_SCHEMA ist? –

0

am Motor DB Je Ihr können Sie ganz einfach die DB Systemtabellen für diese

Für Zugriffsinformationen abfragen ich nicht die Antwort finden kann ich wissen Sie can see the sys tables beim Zugang und von dort können Sie versuchen, und zu bestimmen, wo diese Information ist aber ich bin nicht wirklich sicher, wie man diesen Teil macht. versucht, ein Beispiel zu verwenden, aber jetzt wo

+1

MSysObjects enthält die Liste der Tabellen, es gibt leider keine Entsprechung für Felder. –

2

Fragen Sie, wie Sie die Spaltennamen einer Tabelle in einer Datenbank erhalten können?

Wenn ja, hängt es vollständig von dem Datenbankserver ab, den Sie verwenden.

In SQL 2005 Sie von der INFORMATION_SCHEMA.COLUMNS Ansicht auswählen können

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

IN SQL 2000 Sie SysObjects zu SysColumns beitreten können die Informationen zu erhalten

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

Wie trifft Ihre Antwort auf Access/Jet zu? –

+0

-1 Er fragt nach MS Access. –

+1

Sorry, ich nehme meine -1 zurück, die ursprüngliche Frage war zu diesem Punkt nicht klar. –

4

diese Abfrage ausführen:

select top 1 * 
From foo 

und gehen Sie dann die Listenfelder (und zurückgegebene Werte) in der Ergebnismenge, um die Feldnamen zu erhalten.

+0

Wenn alles, was Sie brauchen, ist Spalte * Namen * dann ist diese schnelle und dreckige Ansatz in Ordnung IMO. Beachten Sie, dass Sie WHERE 0 = 1 (oder ähnlich) hinzufügen können, um sicherzustellen, dass keine Daten zurückgegeben werden. – onedaywhen

+0

Dies funktioniert nicht, wenn Sie Untertitel definiert haben. Es zeigt stattdessen die Beschriftung an. – jpmc26

1

Verwenden Sie die DAO-Automatisierungsklassen. Möglicherweise haben Sie bereits eine Interop-Bibliothek in Ihrer Visual Studio-Installation dafür. Wenn nicht, ist es einfach genug, eins zu erstellen. Fügen Sie einfach einen Verweis auf die DAO-COM-Bibliothek hinzu.

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(); 

Dies ist genauso einfach wie eine Systemtabelle Abfragen (die ich gefunden habe, in Access problematisch zu sein), und Sie können eine Menge von zusätzlichen Informationen auf diese Weise erhalten.

EDIT: ich den Code geändert haben von dem, was ich gestern geschrieben, was ich gerade von VB.NET übersetzt hatte, und die ein paar Stücke fehlte. Ich habe es neu geschrieben und getestet in C# in VS2008.

+0

Von C# aus sind die ADO-Katalogfunktionen möglicherweise einfacher. –

+1

IIRC die Aufrufe von OpenSchema, um die Informationen SCHEMA Ansichten sind nicht einfach für C# und möglicherweise nicht nur für Spaltennamen Wert. – onedaywhen

8

Verwenden IDataReader.GetSchemaTable()

Hier ist ein aktuelles Beispiel, das das Tabellenschema und druckt greift es schlicht und in XML (nur um zu sehen, welche Informationen Sie erhalten):

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()); 
    } 
} 

Points of Interest:

  1. Geben Sie keine Daten zurück, indem Sie eine where-Klausel angeben, die immer als false ausgewertet wird. Das gilt natürlich nur, wenn Sie nicht an den Daten interessiert sind :-).
  2. Verwenden Sie IDataReader.GetSchemaTable(), um eine DataTable mit detaillierten Informationen über die tatsächliche Tabelle abzurufen.

Für meinen Test-Tabelle war die Ausgabe:

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

Ist 'conn.Close()' nicht redundant, da die Verbindung innerhalb eines 'using'-Konstrukts erstellt wird, das die Verbindung schließt, wenn das Konstrukt trotzdem existiert? –

0

für Microsoft SQL in C# Sie folgendes tun:

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); 

schafft so eine Karte von Spaltennamen in seine Index, der wie folgt verwendet werden kann:

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

Ich hatte viel Glück mit der GetSchema-Eigenschaft der OleDb.Connection:

Eine Klasse, um Spaltendaten bereitzustellen. Dies gibt ALLE Spalten in der Datenbank zurück. Die sich ergebende Datentabelle kann dann durch Spaltennamen gefiltert werden, die (meist) entsprechen denen in einem Standard-INFORMATION_SCHEMA gefunden (die MS Access für uns nicht vorgesehen):

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; 
     } 

    } 

Dann die Klasse Konsumieren in einem ziemlich grob und nicht so elegant Beispiel und Filterung auf 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; 

    } 

Bitte beachte, dass ich behaupte nicht, dass dies alles gut, obwohl out-Code ist. Es ist nur ein Beispiel. Aber ich habe so etwas mehrmals benutzt und sogar eine Anwendung erstellt, um eine ganze MS Access Datenbank (Contraints und alle) mit ähnlichen Methoden zu erstellen.

Während ich gesehen habe andere in diesem Thread erwähnen das Schema, es scheint, dass einige der Implementierung übermäßig kompliziert war. . .

Hoffe, dass hilft!

1

Dieser Kodex wird alle Spaltennamen einer Tabelle als eine Klasse mit getter Eigenschaft aller Spaltennamen drucken, die dann in c# Code verwendet werden kann

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 

Ausgang:

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"; } } 

} 
Verwandte Themen