2009-05-13 22 views

risposta

5

questo funziona su sql server 2005 e fino:

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

ma lavoro in Access, e in accesso non funziona – Gold

+1

@Gold, aggiungi il tag "accesso" alla domanda! –

+0

Non funziona in accesso. Puoi spiegare cos'è INFORMATION_SCHEMA? –

0

A seconda del motore DB vostro usando si può facilmente interrogare le tabelle di sistema DB per le informazioni

Per l'accesso non riesco a trovare la risposta che so che can see the sys tables nell'accesso e da lì si poteva cercare di determinare dove questa informazione è, ma non sono davvero sicuro di come fare questa parte. ho provato ad usare un esempio, ma ora ho capito dove

+1

MSysObjects contiene l'elenco di tabelle, purtroppo non ci sono equivalenti per i campi. –

2

Stai chiedendo come puoi ottenere i nomi delle colonne di una tabella in un Database?

Se così dipende completamente dal server database che si sta utilizzando.

In SQL 2005 è possibile selezionare dalla INFORMATION_SCHEMA.COLUMNS View

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

IN SQL 2000 è possibile partecipare a SysObjects SysColumns per avere le informazioni

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

Come si applica la tua risposta ad Access/Jet? –

+0

-1 Chiede informazioni su MS Access. –

+1

Scusa, riprendo il mio -1, la domanda originale non era chiara su questo punto. –

4

eseguita questa interrogazione:

select top 1 * 
From foo 

e quindi accedere ai campi dell'elenco (e ai valori restituiti) nel set di risultati per ottenere i nomi dei campi.

+0

Se tutto ciò di cui hai bisogno è colonna * nomi *, allora questo approccio rapido e sporco è valido IMO. Nota è possibile aggiungere WHERE 0 = 1 (o simile) per garantire che nessun dato venga restituito. – onedaywhen

+0

Questo non funziona se sono state definite didascalie. Mostra invece la didascalia. – jpmc26

1

Utilizzare le classi di automazione DAO. Potresti già avere una libreria di interoperabilità per l'installazione di Visual Studio. In caso contrario, è abbastanza facile crearne uno; basta aggiungere un riferimento alla libreria COM DAO.

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

Questo è altrettanto facile come l'interrogazione di una tabella di sistema (che ho trovato per essere problematico in Access), e si può ottenere un sacco di informazioni aggiuntive in questo modo.

EDIT: Ho modificato il codice da quello che ho postato ieri, che avevo appena tradotto dal VB.NET, e che mancava un paio di pezzi. L'ho riscritto e testato in C# in VS2008.

+0

Da C#, le funzioni del Catalogo ADO potrebbero essere più semplici. –

+1

IIRC le chiamate a OpenSchema per ottenere le VISIONI SCHEMA INFORMAZIONI non sono semplici per C# e potrebbero non valerne la pena solo per i nomi delle colonne. – onedaywhen

8

Usa IDataReader.GetSchemaTable()

Ecco un esempio reale che accede lo schema della tabella e lo stampa pianura e in XML (solo per vedere quali sono le informazioni che si ottiene):

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

Punti di interesse:

  1. Non restituire alcun dato fornendo una clausola where che viene sempre valutata come falsa. Ovviamente questo si applica solo se non sei interessato ai dati :-).
  2. Utilizzare IDataReader.GetSchemaTable() per ottenere un DataTable con informazioni dettagliate sulla tabella effettiva.

Per la mia tabella di prova l'output era:

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

Non è 'rid.Close()' ridondante, poiché la connessione viene creata all'interno di un costrutto 'using', che chiuderà la connessione quando l'esecuzione esiste comunque il costrutto? –

0

per Microsoft SQL in C# è possibile effettuare le seguenti operazioni:

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

crea così una mappa di nome della colonna nella sua indice che può essere utilizzato come segue:

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

Ho avuto fortuna con la proprietà GetSchema di OleDb.Connection:

Una classe per fornire dati di colonna. Ciò restituisce TUTTE le colonne nel database. Il DataTable risultante può essere filtrato da nomi delle colonne che corrispondono (per lo più) a quelle che si trovano in un INFORMATION_SCHEMA standard (che MS Access non fornisce per noi):

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

    } 

Quindi, consumando la classe in un piuttosto grezzo e non-così-elegante esempio, e filtraggio su 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; 

    } 

nota che io non pretendo che questo è tutto bene, anche se fuori il codice. È solo un esempio Ma ho usato qualcosa di simile in diverse occasioni, e in effetti ho persino creato un'applicazione per creare un intero database MS Access (contrappesi e tutto) usando metodi simili.

Mentre ho visto gli altri in questo thread menzionare lo schema get, sembra che alcune implementazioni siano eccessivamente complicate. . .

Spero che questo aiuti!

1

Questo codice stamperà tutti i nome di colonna di una tabella come classe con getter proprietà di tutti i nomi delle colonne che può essere poi utilizzato in c# codice

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 

uscita:

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

} 
Problemi correlati