我有一个包含超过150k行语句的sql脚本(大多数是插入)。我只想在表为空时执行这些插入:
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块内部不起作用。我该如何解决这个问题?
答案 0 :(得分:2)
要对抗巨大的其他区块,您可以使用以下3种策略中的任何一种。
STRATEGY 1
使用SQL Server中的批量插入。只需将所有数据转储到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行。
当然,根据您的业务规则,您可以编写存储过程的insert语句的脚本。如果您的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
答案 1 :(得分:1)
您可以使用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
只打印一张空表 - 希望你能看到它如何适应你的脚本。
答案 2 :(得分:1)
难道你不能简单地在大脚本的开头添加这个块,而不构造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
答案 3 :(得分:0)
如何使用GOTO
语句跳出插入语句?
IF EXISTS (SELECT * FROM [MyTable])
BEGIN
GOTO NODATA
END
--INSERT #1
--...
--Insert #150000
NODATA:
PRINT 'No need to insert data'