Jak mogę uzyskać nazwy pól tabeli bazy danych MS Access?Jak mogę uzyskać nazwy pól tabeli bazy danych?
Czy istnieje zapytanie SQL, którego mogę użyć, lub czy istnieje kod C#, aby to zrobić?
Jak mogę uzyskać nazwy pól tabeli bazy danych MS Access?Jak mogę uzyskać nazwy pól tabeli bazy danych?
Czy istnieje zapytanie SQL, którego mogę użyć, lub czy istnieje kod C#, aby to zrobić?
to będzie działać na serwerze sql 2005 i up:
select * from INFORMATION_SCHEMA.COLUMNS
where TABLE_Name='YourTableName'
order by ORDINAL_POSITION
, ale pracuję w programie Access, aw dostępie to nie działa – Gold
@Gold, dodaj "dostęp" do pytania! –
To nie działa w dostępie. Czy możesz wyjaśnić, czym jest INFORMATION_SCHEMA? –
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
MSysObjects zawiera listę tabel, niestety nie ma odpowiednika dla pól. –
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'
Jak twoja odpowiedź ma zastosowanie do Access/Jet? –
-1 On pyta o MS Access. –
Przepraszam, odbieram moje -1, pierwotne pytanie nie było jasne w tej kwestii. –
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.
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
To nie działa, jeśli masz zdefiniowane napisy. Zamiast tego pokazuje podpis. – jpmc26
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.
Z katalogu C# funkcje katalogu ADO mogą być łatwiejsze. –
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
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:
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>
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? –
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(); }
}
}
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!
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"; } }
}
My sugerowane rozwiązanie nie jest ograniczone do baz danych MS Access. – VVS