开始结束块内的许多插入
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'
我有一个 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'