2009-05-13 15 views

Respuesta

5

esto va a funcionar en el servidor SQL 2005 y hasta:

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

pero yo trabajo en Access, y en el acceso no es el trabajo – Gold

+1

@Gold, agregue la etiqueta de "acceso" a la pregunta! –

+0

Esto no funciona en el acceso. ¿Puedes explicarme qué es INFORMATION_SCHEMA? –

0

Dependiendo del motor de base de datos utilizando su poder consultar fácilmente las tablas del sistema de base de datos para que la información

Para el acceso no puedo encontrar la respuesta sé que can see the sys tables en el acceso y desde allí se podía tratar de determinar dónde esa información es pero no estoy seguro de cómo hacer esta parte. intenté usar un ejemplo pero obtuve ahora donde

+1

MSysObjects contiene la lista de tablas, desafortunadamente no hay un equivalente para los campos. –

2

¿Está preguntando cómo puede obtener los nombres de columna de una tabla en una base de datos?

Si es así, depende completamente del servidor de base de datos que esté utilizando.

En SQL 2005 puede seleccionar desde el INFORMATION_SCHEMA.COLUMNS Ver

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

en SQL 2000 puede unirse a Sysobjects syscolumns para obtener la información

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

¿Cómo se aplica su respuesta a Access/Jet? –

+0

-1 Pregunta sobre MS Access. –

+1

Lo siento, recupero mi -1, la pregunta original no estaba clara en ese punto. –

4

ejecuta esta consulta:

select top 1 * 
From foo 

y recorra los campos de la lista (y los valores devueltos) en el conjunto de resultados para obtener los nombres de los campos.

+0

Si todo lo que necesita son columnas * nombres * entonces este enfoque rápido y sucio está bien IMO. Tenga en cuenta que puede agregar WHERE 0 = 1 (o similar) para garantizar que no se devuelven datos. – onedaywhen

+0

Esto no funciona si tiene leyendas definidas. Muestra el título en su lugar. – jpmc26

1

Utilice las clases de automatización DAO. Es posible que ya tenga una biblioteca de interoperabilidad en su instalación de Visual Studio. Si no, es bastante fácil crear uno; solo agregue una referencia a la biblioteca 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(); 

Esto es tan fácil como consultar una tabla del sistema (que he encontrado para ser problemático en Access), y se puede obtener una gran cantidad de información adicional de esta manera.

EDIT: He modificado el código de lo que he publicado ayer, que acababa traducida de VB.NET y que faltaba un par de piezas. Lo reescribí y lo probé en C# en VS2008.

+0

Desde C#, las funciones del Catálogo ADO pueden ser más fáciles. –

+1

IIRC las llamadas a OpenSchema para obtener la INFORMACIÓN Las visualizaciones de SCHEMA no son sencillas para C# y pueden no valer la pena solo para los nombres de columna. – onedaywhen

8

Uso IDataReader.GetSchemaTable()

He aquí un ejemplo real que accede al esquema de la tabla y lo imprime simple y en XML (sólo para ver qué tipo de información se obtiene):

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

Puntos de interés:

  1. No devuelva ningún dato dando una cláusula where que siempre se evalúa como falsa. Por supuesto, esto solo se aplica si no estás interesado en los datos :-).
  2. Use IDataReader.GetSchemaTable() para obtener una DataTable con información detallada acerca de la tabla actual.

Por mi tabla de prueba la salida fue:

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

¿No es 'conn.Close()' redundante, ya que la conexión se crea dentro de una construcción 'using', que cerrará la conexión cuando la ejecución exista de todos modos? –

0

para SQL Microsoft en C# se puede hacer lo siguiente:

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

por lo tanto crea un mapa de nombre de la columna en su índice que se puede utilizar de la siguiente manera:

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

He tenido buena suerte con la propiedad GetSchema de OleDb.Connection:

Una clase para proporcionar datos de columna. Esto devuelve TODAS las columnas en la base de datos. El DataTable resultante puede entonces ser filtrada por los nombres de columna que corresponden (en su mayoría) a los encontrados en una INFORMATION_SCHEMA estándar (que MS Access no proporciona para nosotros):

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

    } 

Entonces, consumo de la clase de una forma bastante crudo y ejemplo no tan elegante, y filtrado de 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; 

    } 

Tenga en cuenta que yo no pretendo que todo esto es así, aunque fuera código. Es solo un ejemplo. Pero he usado algo como esto en varias ocasiones, y de hecho incluso he creado una aplicación para crear una secuencia de comandos de una base de datos completa de MS Access (contraints y todo) usando métodos similares.

Si bien he visto a otros en este hilo mencionar el esquema get, parece que algo de la implementación fue demasiado complicado. . .

Espero que ayude!

1

Este código imprimirá todos los nombres de columna de una tabla como una clase con getter propiedad de todos los nombres de las columnas que se puede utilizar a continuación en c# código

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 

Salida:

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

} 
Cuestiones relacionadas