【问题标题】:How to insert 1000 rows at a time如何一次插入1000行
【发布时间】:2013-08-31 16:01:06
【问题描述】:

我制作了 Wpf 应用程序。我想用网格中的 1000 个值来测试它。我想检查我的网格是否会快速加载 1000 条数据记录。那么如何编写一个查询来在我的数据库表中插入超过 1000 条记录。我可以用for循环吗?

Insert into db(@names,@email,@password) Values('abc','def','mypassword');

我正在使用 Sql-Server 2012 和 ADO.net 连接!我想在数据库中执行这个查询来生成 1000 行

编辑

如果我想插入唯一名称怎么办?

【问题讨论】:

  • 你是如何生成这 1000 个值的?您是否使用 DataTable 来存储您的值?你看过SqlBulkCopy吗?现在您的问题过于宽泛,因为根据您遗漏的细节,有很多方法可以做到这一点。请详细说明您正在使用什么技术(ADO.NET、Entity Framework、NHibernate)以及您是如何使用它的。
  • @ScottChamberlain 是的,我正在使用名为 db 的数据库表。我想写一个查询来在我的表中生成 1000 行。
  • @Zoya 他在问这 1000 个名字的来源。您是否尝试生成 1000 个相同的名称,1000 个不同的名称(如果是,如何生成)?你已经有一个包含 1000 个名字的列表了吗?请更好地定义您的问题。
  • 当我需要一个一次性脚本来插入一堆测试数据时,我经常会找到一个单词列表(比如一个字典文件),根据需要获取尽可能多的单词并使用 multi - 在 Sublime Text 或类似中编辑光标以围绕它们构建 SQL。

标签: sql-server database


【解决方案1】:

我创建了一个包含三列 id, student,agestudent 表。给你看这个例子

declare @id int 
select @id = 1
while @id >=1 and @id <= 1000
begin
    insert into student values(@id, 'jack' + convert(varchar(5), @id), 12)
    select @id = @id + 1
end

这是关于示例的结果

【讨论】:

  • @id &gt;= 1while 子句中的原因是什么?我认为只有@id &lt;= 1000 是必要的。
  • 我故意否决了这个答案。在我看来,这篇文章不应该被标记为“答案”。(“Aaron Bertrand”的答案是正确的。)尝试 100 万次迭代,看看这个循环需要多长时间。问题是日志文件不必要地被每个插入语句填充,这会减慢进程并损坏日志文件。
  • 尝试了 1M 行,耗时 19 秒.... 诚然,我的数据库运行在 18 个 CPU 内核、150GB RAM 和完整的 SSD 上,但这似乎并不慢。我不会说它“损坏”日志文件,只是正常写入。
【解决方案2】:

如果您的应用程序中有一个 DataTable,这就是 1000 个名称的来源,您可以为此使用表值参数。

一、表类型:

CREATE TYPE dbo.Names AS TABLE
(
  Name NVARCHAR(255),
  email VARCHAR(320),
  [password] VARBINARY(32) -- surely you are not storing this as a string!?
);

然后是使用这个的程序:

CREATE PROCEDURE dbo.Names_BulkInsert
  @Names dbo.Names READONLY
AS
BEGIN
  SET NOCOUNT ON;

  INSERT dbo.RealTable(Name, email, password)
    SELECT Name, email, password
    FROM @Names;
END
GO

那么你的 C# 代码可以说:

SqlCommand cmd = new SqlCommand("dbo.Names_BulkInsert", connection_object);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter names = cmd.Parameters.AddWithValue("@Names", DataTableName);
names.SqlDbType = SqlDbType.Structured;
cmd.ExecuteNonQuery();

如果你只想生成 1000 行随机值

;WITH x AS
(
  SELECT TOP (1000) n = REPLACE(LEFT(name,32),'_','')
  FROM sys.all_columns ORDER BY NEWID()
)
-- INSERT dbo.sometable(name, email, [password])
SELECT 
  name = LEFT(n,3),
  email = RIGHT(n,5) + '@' + LEFT(n,2) + '.com', 
  [password] = CONVERT(VARBINARY(32), SUBSTRING(n, 1, 32))  
FROM x;

在这两种情况下,您都不应该使用 while 循环或游标。恕我直言。

【讨论】:

    【解决方案3】:

    您可以通过从结果中插入来插入多条记录:

    insert into db (@names,@email,@password) 
    select 'abc','def','mypassword' union all
    select 'abc','def','mypassword' union all
    select 'abc','def','mypassword' union all
    select 'abc','def','mypassword' union all
    select 'abc','def','mypassword' union all
    select 'abc','def','mypassword'
    

    只需添加您喜欢的任意数量的记录。不过,查询的复杂性可能会受到限制,因此一次添加多达 1000 条记录是不可能的。

    【讨论】:

    • @ZoyaSheikh:是的,只需在选择语句中输入唯一名称即可。
    • 他们不会重复吗?
    • @ZoyaSheikh:仅当您多次运行查询时。如果需要多次运行得到 1000 条记录,则需要在每次之间更改名称以获得表中唯一的名称。
    • 那么这里生成 1000 个唯一名称的建议是手动输入 1000 个不同的名称?
    • @AaronBertrand:是的。如果您想生成唯一的名称,那就是另一个问题了。
    【解决方案4】:

    您当然可以使用循环,也可以将它们插入到单个语句中,例如

    Insert into db
    (names,email,password) 
    Values
    ('abc','def','mypassword')
    ,('ghi','jkl','mypassword2')
    ,('mno','pqr','mypassword3')
    

    这真的取决于您从哪里获取数据。

    如果您使用循环,将其包装在事务中会使其更快一些。

    更新

    如果我想插入唯一名称怎么办?

    如果要插入唯一名称,则需要生成具有唯一名称的数据。一种方法是使用 Visual Studio to generate test data

    【讨论】:

    • "如果您使用循环,将其包装在事务中会使其更快一些。"真的吗?这很有趣。我想这是有道理的。我将在 BEGIN TRAN 中封装一个非常慢的循环,看看会发生什么。
    • @GeoffGriswald 是的,确实如此,但有一个(权衡。如果您的事务变得庞大,您可能会影响并发性,甚至最终得到完整的事务日志。所以如果您有大量的行要插入,您应该为每 N 行创建一个新事务,其中 N 的适当值将特定于您的环境。
    • 有趣。我最终每 1,000 行就处理一次新事务。我的过程需要一个小时,现在缩短到 5 分钟。
    【解决方案5】:

    使用@Aaron Bertrand 的想法 (FROM sys.all_columns),这将创建 1000 条记录:

     SELECT TOP (1000) LEFT(name,20) as names,
                       RIGHT(name,12) + '@' + LEFT(name,12) + '.com' as email, 
                       sys.fn_sqlvarbasetostr(HASHBYTES('MD5', name)) as password
     INTO db
     FROM sys.all_columns
    

    SQLFIDDLE

    【讨论】:

      【解决方案6】:

      对了,你为什么不使用通过存储过程插入 XML 数据呢?

      这是执行此操作的链接... Inserting Bulk Data through XML-Stored Procedure

      【讨论】:

        【解决方案7】:
        DECLARE @X INT = 1
        WHILE @X <=1000
        BEGIN
            INSERT INTO dbo.YourTable (ID, Age)
            VALUES(@X,LEFT(RAND()*100,2) 
            SET @X+=1
        END;
        
            enter code here
        DECLARE @X INT = 1
        WHILE @X <=1000
        BEGIN
            INSERT INTO dbo.YourTable (ID, Age)
            VALUES(@X,LEFT(RAND()*100,2) 
            SET @X+=1
        END;
        

        【讨论】:

          【解决方案8】:

          最简单的方法。

          只需在 10 秒内停止执行。

          Create table SQL_test  ( ID INT IDENTITY(1,1), UserName varchar(100)) 
          while 1=1 
          insert into SQL_test values ('TEST') 
          

          【讨论】:

            【解决方案9】:

            您也可以使用以下 CTE。您可以根据需要对其进行修改。但这会将相同的值添加到学生 CTE 中。

            这将添加 1000 条记录,但您可以将其更改为 10000 条或最多 32767 条

            ;WITH thetable(rowid,sname,semail,spassword) AS
            (
                SELECT 1  , 'name' , 'email' , 'password'
                UNION ALL
                SELECT rowid+1 ,'name' , 'email' , 'password' 
                FROM thetable WHERE rowid < 1000
            )
            
            SELECT rowid,sname,semail,spassword 
            FROM thetable ORDER BY rowid
            OPTION (MAXRECURSION 1000);
            

            【讨论】:

              猜你喜欢
              • 2017-12-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多