我无法确定最佳方法。我们正在维护一个复杂的数据库,普通的业务分析师会遇到很多麻烦。另一位开发人员创建了几个存储过程作为报告,我们已根据需要将这些用户导出到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();
}
}
值得注意的是:
修改:
这是我的“最终解决方案”。建议使用链接服务器的评论肯定会是一种更简单的方法,但有一件事阻止我做起初我没有想到的事情,数据需要存在于Access数据库中,因为用户可能会消耗数据远离他们对底层数据库的网络访问权限。因此,我一直在抨击这种方法,这就是我想出的:
请注意,我仍然愿意接受“更好的方式”的建议,但这解决了我当前的问题
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();
}
}
答案 0 :(得分:1)
这是我的“最终解决方案”。建议使用链接服务器的评论肯定会是一种更简单的方法,但有一件事阻止我做起初我没有想到的事情,数据需要存在于Access数据库中,因为用户可能会消耗数据远离他们对底层数据库的网络访问权限。因此,我一直在抨击这种方法,这就是我想出的:
请注意,我仍然愿意接受“更好的方式”的建议,但这解决了我当前的问题
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();
}
}