我很难确定执行此操作的最佳方法。我们正在维护一个复杂的数据库,普通业务分析师在处理这个数据库时会遇到很多麻烦。另一位开发人员创建了几个存储过程作为报告,我们一直在为用户按需导出到excel电子表格中。
客户端请求将这些结果导出到访问数据库中。
如果这是2或3列,我只需要创建一个"模板"accdb文件,并将存储过程的结果推到那里。然而,这个查询现在返回了100多个列,并且了解客户端,它将在未来进行扩展。所以我正试图根据结果集动态创建表格。。。不管是什么。
我认为正确的方法是使用SqlDataReader
,但我一直在思考如何获得正确的"SQL"式字段类型。我当前的代码看起来像:
static void CreateAccessTableFromReader(string tableName, SqlDataReader reader) {
List<string> columns = new List<string>();
string createTable = @"CREATE TABLE {0} ({1})";
int fieldCount = reader.FieldCount;
for (int i = 0; i < fieldCount; i++) {
columns.Add(String.Format("[{0}] {1}({2})",
//column name (this seems to be right)
reader.GetName(i),
//column type __(this is wrong.. I want 'VARCHAR, INT, etc')__
reader.GetProviderSpecificFieldType(i),
//column size (e.g. the numeric part of VARCHAR(15))
reader.???
));
//right now I'm getting results from the above line like:
//[ColumnName] System.Data.SqlTypes.SqlString
//and I'm looking for something like:
//[ColumnName] VARCHAR(15)
}
using (var cmd = conn_Access.CreateCommand()) {
cmd.CommandType = CommandType.Text;
cmd.CommandText = String.Format(createTable, tableName, String.Join(", ", columns));
cmd.ExecuteNonQuery();
}
}
值得注意的是:
- 根据此链接,MSSQL和Access之间将存在的唯一类型应完全匹配:http://msdn.microsoft.com/en-us/library/bb177899.aspx
编辑:
这是我的"最终解决方案"。建议使用链接服务器的评论当然是一种更容易的方法,但有一件事阻止了我这样做,这在我最初没有想到,数据需要存在于Access DB中,因为用户可能会在远离他们可以访问底层数据库的网络的地方使用数据。因此,我一直在研究这种方法,下面是我想到的:
注意,我仍然愿意接受"更好的方法"的建议,但这解决了我目前的问题
static void CreateTableFromReader(string tableName, SqlDataReader reader) {
List<string> columns = new List<string>();
string createTable = @"CREATE TABLE {0} ({1})";
var dt = reader.GetSchemaTable();
foreach (DataRow dr in dt.Rows) {
switch (dr["DataTypeName"].ToString().ToLower()) {
case "varchar":
columns.Add(String.Format("[{0}] {1}({2})",
dr["ColumnName"],
dr["DataTypeName"],
dr["ColumnSize"]
));
break;
case "money": //i know this is redundant but being explicit helps clarity sometimes
case "date":
case "integer":
default:
columns.Add(String.Format("[{0}] {1}",
dr["ColumnName"],
dr["DataTypeName"]
));
break;
}
}
using (var cmd = conn_Access.CreateCommand()) {
cmd.CommandType = CommandType.Text;
cmd.CommandText = String.Format(createTable, tableName, String.Join(", ", columns));
cmd.ExecuteNonQuery();
}
}
这是我的"最终解决方案"。建议使用链接服务器的评论当然是一种更容易的方法,但有一件事阻止了我这样做,这在我最初没有想到,数据需要存在于Access DB中,因为用户可能会在远离他们可以访问底层数据库的网络的地方使用数据。因此,我一直在研究这种方法,下面是我想到的:
注意,我仍然愿意接受"更好的方法"的建议,但这解决了我目前的问题
static void CreateTableFromReader(string tableName, SqlDataReader reader) {
List<string> columns = new List<string>();
string createTable = @"CREATE TABLE {0} ({1})";
var dt = reader.GetSchemaTable();
foreach (DataRow dr in dt.Rows) {
switch (dr["DataTypeName"].ToString().ToLower()) {
case "varchar":
columns.Add(String.Format("[{0}] {1}({2})",
dr["ColumnName"],
dr["DataTypeName"],
dr["ColumnSize"]
));
break;
case "money": //i know this is redundant but being explicit helps clarity sometimes
case "date":
case "integer":
default:
columns.Add(String.Format("[{0}] {1}",
dr["ColumnName"],
dr["DataTypeName"]
));
break;
}
}
using (var cmd = conn_Access.CreateCommand()) {
cmd.CommandType = CommandType.Text;
cmd.CommandText = String.Format(createTable, tableName, String.Join(", ", columns));
cmd.ExecuteNonQuery();
}
}