【问题标题】:Converting a DataTable to an CREATE TABLE + INSERT script for SQL in C#在 C# 中将 DataTable 转换为 SQL 的 CREATE TABLE + INSERT 脚本
【发布时间】:2011-07-10 18:47:48
【问题描述】:

我需要从 DataTable 以及其中的 DATA 生成 TSQL 脚本。 这不是一个单一的插入。除此之外,我也需要创建表(相同的数据表结构)

所以:我有一个填充数据的 DataTable。我想要创建此 DataTable 结构的 TSQL 脚本以及 SQL SERVER 中的数据(CREATE TABLE + INSERT)

提前谢谢你 并且特别感谢 John Saunders 帮助我更正了这个问题。

【问题讨论】:

  • 您使用的是哪个版本的 .NET? DataTable 是相当原始的技术,没有内置的方式来做你想要的。
  • 我使用的是 Framework 3.5 vs 2010
  • 那么您应该查看实体框架,它具有创建数据库模型、创建表然后更新它的能力。 DataTable 已经过时了。
  • 在我的情况下提供了一个数据表,我需要创建一个数据集来获取结构吗?要读取数据表中的每一行,我可以这样做并附加它并插入一串字符串。 For Each iRow as Datarow in dtTable string strSQL = "INSERT INTO TestTable(Col1,Col2) VALUES (" + iRow.item("Col1") + "," + iRow.item("Col1") + ")";
  • 废话,DataTable 并没有“过时”。实体框架对于很多项目来说都是多余的。

标签: c# sql tsql datatable


【解决方案1】:

看看:Generate SQL INSERT commands programmatically

本质上,代码是循环遍历 DataTable.Columns 集合以生成 INSERT 语句的列列表。然后它循环遍历 DataTable 的值以创建具有值的参数。

【讨论】:

    【解决方案2】:

    首先,我会用这个对象来build your CREATE TABLE command.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data.SqlClient;
    using System.Data;
    
    namespace Toolkit
    {
        public class SqlTableCreator
        {
            #region Instance Variables
            private SqlConnection _connection;
            public SqlConnection Connection
            {
                get { return _connection; }
                set { _connection = value; }
            }
    
            private SqlTransaction _transaction;
            public SqlTransaction Transaction
            {
                get { return _transaction; }
                set { _transaction = value; }
            }
    
            private string _tableName;
            public string DestinationTableName
            {
                get { return _tableName; }
                set { _tableName = value; }
            }
            #endregion
    
            #region Constructor
            public SqlTableCreator() { }
            public SqlTableCreator(SqlConnection connection) : this(connection, null) { }
            public SqlTableCreator(SqlConnection connection, SqlTransaction transaction)
            {
                _connection = connection;
                _transaction = transaction;
            }
            #endregion
    
            #region Instance Methods
            public object Create(DataTable schema)
            {
                return Create(schema, null);
            }
            public object Create(DataTable schema, int numKeys)
            {
                int[] primaryKeys = new int[numKeys];
                for (int i = 0; i < numKeys; i++)
                {
                    primaryKeys[i] = i;
                }
                return Create(schema, primaryKeys);
            }
            public object Create(DataTable schema, int[] primaryKeys)
            {
                string sql = GetCreateSQL(_tableName, schema, primaryKeys);
    
                SqlCommand cmd;
                if (_transaction != null && _transaction.Connection != null)
                    cmd = new SqlCommand(sql, _connection, _transaction);
                else
                    cmd = new SqlCommand(sql, _connection);
    
                return cmd.ExecuteNonQuery();
            }
    
            public object CreateFromDataTable(DataTable table)
            {
                string sql = GetCreateFromDataTableSQL(_tableName, table);
    
                SqlCommand cmd;
                if (_transaction != null && _transaction.Connection != null)
                    cmd = new SqlCommand(sql, _connection, _transaction);
                else
                    cmd = new SqlCommand(sql, _connection);
    
                return cmd.ExecuteNonQuery();
            }
            #endregion
    
            #region Static Methods
    
            public static string GetCreateSQL(string tableName, DataTable schema, int[] primaryKeys)
            {
                string sql = "CREATE TABLE [" + tableName + "] (\n";
    
                // columns
                foreach (DataRow column in schema.Rows)
                {
                    if (!(schema.Columns.Contains("IsHidden") && (bool)column["IsHidden"]))
                    {
                        sql += "\t[" + column["ColumnName"].ToString() + "] " + SQLGetType(column);
    
                        if (schema.Columns.Contains("AllowDBNull") && (bool)column["AllowDBNull"] == false)
                            sql += " NOT NULL";
    
                        sql += ",\n";
                    }
                }
                sql = sql.TrimEnd(new char[] { ',', '\n' }) + "\n";
    
                // primary keys
                string pk = ", CONSTRAINT PK_" + tableName + " PRIMARY KEY CLUSTERED (";
                bool hasKeys = (primaryKeys != null && primaryKeys.Length > 0);
                if (hasKeys)
                {
                    // user defined keys
                    foreach (int key in primaryKeys)
                    {
                        pk += schema.Rows[key]["ColumnName"].ToString() + ", ";
                    }
                }
                else
                {
                    // check schema for keys
                    string keys = string.Join(", ", GetPrimaryKeys(schema));
                    pk += keys;
                    hasKeys = keys.Length > 0;
                }
                pk = pk.TrimEnd(new char[] { ',', ' ', '\n' }) + ")\n";
                if (hasKeys) sql += pk;
    
                sql += ")";
    
                return sql;
            }
    
            public static string GetCreateFromDataTableSQL(string tableName, DataTable table)
            {
                string sql = "CREATE TABLE [" + tableName + "] (\n";
                // columns
                foreach (DataColumn column in table.Columns)
                {
                    sql += "[" + column.ColumnName + "] " + SQLGetType(column) + ",\n";
                }
                sql = sql.TrimEnd(new char[] { ',', '\n' }) + "\n";
                // primary keys
                if (table.PrimaryKey.Length > 0)
                {
                    sql += "CONSTRAINT [PK_" + tableName + "] PRIMARY KEY CLUSTERED (";
                    foreach (DataColumn column in table.PrimaryKey)
                    {
                        sql += "[" + column.ColumnName + "],";
                    }
                    sql = sql.TrimEnd(new char[] { ',' }) + "))\n";
                }
    
                //if not ends with ")"
                if ((table.PrimaryKey.Length == 0) && (!sql.EndsWith(")")))
                {
                    sql += ")";
                }
    
                return sql;
            }
    
            public static string[] GetPrimaryKeys(DataTable schema)
            {
                List<string> keys = new List<string>();
    
                foreach (DataRow column in schema.Rows)
                {
                    if (schema.Columns.Contains("IsKey") && (bool)column["IsKey"])
                        keys.Add(column["ColumnName"].ToString());
                }
    
                return keys.ToArray();
            }
    
            // Return T-SQL data type definition, based on schema definition for a column
            public static string SQLGetType(object type, int columnSize, int numericPrecision, int numericScale)
            {
                switch (type.ToString())
                {
                    case "System.String":
                        return "VARCHAR(" + ((columnSize == -1) ? "255" : (columnSize > 8000) ? "MAX" : columnSize.ToString() ) + ")";
    
                    case "System.Decimal":
                        if (numericScale > 0)
                            return "REAL";
                        else if (numericPrecision > 10)
                            return "BIGINT";
                        else
                            return "INT";
    
                    case "System.Double":
                    case "System.Single":
                        return "REAL";
    
                    case "System.Int64":
                        return "BIGINT";
    
                    case "System.Int16":
                    case "System.Int32":
                        return "INT";
    
                    case "System.DateTime":
                        return "DATETIME";
    
                    case "System.Boolean":
                        return "BIT";
    
                    case "System.Byte":
                        return "TINYINT";
    
                    case "System.Guid":
                        return "UNIQUEIDENTIFIER";
    
                    default:
                        throw new Exception(type.ToString() + " not implemented.");
                }
            }
    
            // Overload based on row from schema table
            public static string SQLGetType(DataRow schemaRow)
            {
                return SQLGetType(schemaRow["DataType"],
                                    int.Parse(schemaRow["ColumnSize"].ToString()),
                                    int.Parse(schemaRow["NumericPrecision"].ToString()),
                                    int.Parse(schemaRow["NumericScale"].ToString()));
            }
            // Overload based on DataColumn from DataTable type
            public static string SQLGetType(DataColumn column)
            {
                return SQLGetType(column.DataType, column.MaxLength, 10, 2);
            }
            #endregion
        }
    }
    

    然后我会使用 SQL BulkCopy 而不是单独的 INSERT 语句。

    public static void BulkInsertDataTable(string connectionString, string tableName, DataTable table)
            {
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    SqlBulkCopy bulkCopy =
                        new SqlBulkCopy
                        (
                        connection,
                        SqlBulkCopyOptions.TableLock |
                        SqlBulkCopyOptions.FireTriggers |
                        SqlBulkCopyOptions.UseInternalTransaction,
                        null
                        );
    
                    bulkCopy.DestinationTableName = tableName;
                    connection.Open();
    
                    bulkCopy.WriteToServer(table);
                    connection.Close();
                }
            }
    

    【讨论】:

    • 您的 VARCHAR 缺少结束括号。试试这个 VARCHAR(" + ((table.Columns[i].MaxLength == -1) ? "255), " : (table.Columns[i].MaxLength > 8000) ? "MAX), " : table.Columns [i].MaxLength.ToString() + "), "));
    【解决方案3】:

    如果您想从表中创建insert 脚本,请使用我创建的工具。 这会根据给定的条件在多个表上创建 Insert 脚本:

    IF NOT EXISTS (Select 1 from Table1 WHERE Col1='Col1' AND Col2='Col2')
    INSERT INTO Table1 (Col1,Col2,Col3,Col4) VALUES (1,'abc',null,'2012-01-01')
    

    这里是链接:http://www.codeproject.com/Tips/330864/Generate-Insert-script-to-extract-data

    【讨论】:

    • 那篇文章我看了两遍,但不清楚它在做什么。
    【解决方案4】:
    public void createsqltable(DataTable dt,string tablename)
            {
                string strconnection = "";
                string table = "";
                table += "IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[" + tablename + "]') AND type in (N'U'))";
                table += "BEGIN ";
                table += "create table " + tablename + "";
                table += "(";
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    if (i != dt.Columns.Count-1)
                        table += dt.Columns[i].ColumnName + " " + "varchar(max)" + ",";
                    else
                        table += dt.Columns[i].ColumnName + " " + "varchar(max)";
                }
                table += ") ";
                table += "END";
                InsertQuery(table,strconnection);
                CopyData(strconnection, dt, tablename);
            }
            public void InsertQuery(string qry,string connection)
            {
    
    
                SqlConnection _connection = new SqlConnection(connection);
                SqlCommand cmd = new SqlCommand();
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = qry;
                cmd.Connection = _connection;
                _connection.Open();
                cmd.ExecuteNonQuery();
                _connection.Close();
            }
            public static void CopyData(string connStr, DataTable dt, string tablename)
            {
                using (SqlBulkCopy bulkCopy =
                new SqlBulkCopy(connStr, SqlBulkCopyOptions.TableLock))
                {
                    bulkCopy.DestinationTableName = tablename;
                    bulkCopy.WriteToServer(dt);
                }
            }
    

    【讨论】:

    • 我在dt.Columns[i].ColumnName 上添加了花括号,以防止列名包含空格时引发错误
    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2011-12-21
    • 2013-10-14
    • 2016-10-16
    • 2010-12-28
    • 1970-01-01
    • 2018-09-28
    相关资源
    最近更新 更多