开始结束块内的许多插入

Many inserts inside a begin-end block

我有一个 sql 脚本,其中包含超过 150k 行的语句(其中大部分是插入语句)。如果 table 为空,我只想执行这些插入:

IF EXISTS (SELECT * FROM [MyTable])
BEGIN
    PRINT 'No need to insert data'
    --Stop executing script
END
ELSE
BEGIN
    --INSERT #1
    --...
    --Insert #150000
END

问题:似乎 ELSE 块太大了。我尝试使用 GO,但它在 BEGIN-END 块中不起作用。我该如何解决这个问题?

为了应对巨大的 else 块,您可以使用以下 3 种策略中的任何一种。

STRATEGY 1

使用来自 SQL 服务器的批量插入。只需将所有数据转储到一个 csv 文件中,然后在您的 else 块中使用以下语句。将 csv 文件存储在您的计算机上,并在下面的语句中的 FROM 之后给出它的 UNC 路径。这样,您的 else 块中将只有一行。

BULK INSERT dbo.MyTable
FROM '\share\somepath\myTableInsertData.csv'
WITH (FORMAT = 'CSV'); 

STRATEGY 2

编写一次仅插入 x 行的存储过程。然后您可以在 While loop 中调用此存储过程,您的 else 块将非常小。您将在原始 SQL 的 while 循环中重复调用此存储过程,然后 else 块将结束只是几行 t-sql 代码。

请注意,您可以通过为变量 @numberOfRowsAtaTime 使用适当的值来控制存储过程一次插入多少行。我已经使用了 1000,所以在一次存储过程调用中插入了 1000 行。

当然,根据您的业务规则,您可以编写存储过程的插入语句的脚本。如果您的 INSERTS 中有一个模式,那么您可以将该模式编入下面的存储过程逻辑中。

存储过程

CREATE PROCEDURE dbo.insertXRows
    @startIndex INT,
    @numberOfRows INT 
AS
BEGIN

    SET NOCOUNT ON;

    DECLARE @counter INT;
    SET @counter = @startIndex;

    WHILE @counter < (@startIndex + @numberOfRows -1)
    BEGIN 
    -- Insert statements for rows goes here
    --INSERT FOR @counter -- @counter would be different for each iteration
      SET @counter =  @counter + 1;
    END
END
GO

你的SQL

IF EXISTS (SELECT * FROM [MyTable])
BEGIN
    PRINT 'No need to insert data'
    --Stop executing script
END
ELSE
BEGIN

    declare @insertRowCounter int;
    set @insertRowCounter = 1;
    declare @numberOfRowsAtaTime int;
    set @numberOfRowsAtaTime = 1000;
    WHILE @insertRowCounter <= 150000
      EXEC dbo.insertXRows @insertRowCounter, @numberOfRowsAtaTime -- insert 1000 rows at a time
      SET @insertRowCounter = @insertRowCounter + @numberOfRowsAtaTime; 
    END
END

STRATEGY 3

想出10个存储过程,使每个存储过程有15000个INSERTS。然后只需从您的 else 块中调用这 10 个存储过程。

10 个存储过程

CREATE PROCEDURE dbo.insertProc1
  AS
BEGIN

    SET NOCOUNT ON;

    --INSERT1
    --INSERT2

     --INSERT15000

    END
END
GO



CREATE PROCEDURE dbo.insertProc2
  AS
BEGIN

    SET NOCOUNT ON;

    --INSERT15001
    --INSERT15002

     --INSERT3000

    END
END
GO

你的SQL

IF EXISTS (SELECT * FROM [MyTable])
BEGIN
    PRINT 'No need to insert data'
    --Stop executing script
END
ELSE
BEGIN
   EXEC insertProc1
   EXEC insertProc2
   EXEC insertProc3
   EXEC insertProc4
   EXEC insertProc5
   EXEC insertProc6
   EXEC insertProc7
   EXEC insertProc8
   EXEC insertProc9
   EXEC insertProc10
END

你可以利用 NOEXEC:

create table T (ID int not null)
go
if 1=1
begin
    set noexec on
end
go
insert into T(ID) values (1),(2),(3)
--Repeat more inserts
go
set noexec off
go
select * from T

它只打印一个空的 table - 希望您能看到这将如何适应您的脚本。

您不能在没有 else begin ... end 构造的情况下简单地将此块添加到您的大脚本的开头吗?

IF EXISTS (SELECT * FROM [MyTable])
BEGIN
    PRINT 'No need to insert data'
    --Stop executing script and return
    RETURN
END
--Your old script starts here

使用GOTO语句跳出插入语句怎么样?

IF EXISTS (SELECT * FROM [MyTable])
BEGIN
    GOTO NODATA
END

--INSERT #1
--...
--Insert #150000

NODATA:
    PRINT 'No need to insert data'