我需要运行140,000个INSERT语句。我试图将记录插入数据库表,然后将创建的PK输入临时表,然后返回。它看起来像这样:
CREATE PROCEDURE sp_MassInsertProcedure
@PassInVariable int
AS
CREATE TABLE #TempTable(OriginalID int IDENTITY(1,1), NewID int);
--These two inserts are essentially repeated 70,000 times
INSERT INTO MyDBTable (something, something, something) VALUES (1, 2, @PassInVariable);
INSERT INTO #TempTable(NewID) SELECT SCOPE_IDENTITY();
SELECT * FROM #TempTable;
DROP TABLE #TempTable;
我有一些其他存储过程就像这样有最多2000个插入语句,这种方式完美,但我认为由于这个特定SP中的语句数量,它给了我"查询完成错误&# 34;当我尝试创建程序时,但实际上并没有创建程序。
然后我每200个插入语句添加一个GO,但是在第一个GO执行后,必须释放临时表,并且我得到" TempTable不可用"错误(在第一次GO执行后,我也得到@PassInVariable的相同错误)。奇怪的是,当我将上述SQL放在标准脚本(而不是存储过程)中时,它可以工作。
所以我的问题是,是否有人知道如何在单个存储过程中持久化临时表/变量,该存储过程通过GO命令使用多个批处理执行?
CREATE PROCEDURE sp_MassInsertProcedure
@PassInVariable int
AS
CREATE TABLE #TempTable(OriginalID int IDENTITY(1,1), NewID int);
--These inserts are essentially repeated 70,000 times
INSERT INTO MyDBTable (something, something, something) VALUES (1, 2, @PassInVariable);
INSERT INTO #TempTable(NewID) SELECT SCOPE_IDENTITY();
GO
INSERT INTO MyDBTable (something, something, something) (1, 2, @PassInVariable);
INSERT INTO #TempTable(NewID) SELECT SCOPE_IDENTITY();
SELECT * FROM #TempTable;
DROP TABLE #TempTable;
答案 0 :(得分:0)
Ben,这是一个常见的错误概念,即" GO"在SQLServer中。 " GO"它不是T-SQL的一部分,它是SQLServer工具(ssms,sqlcmd,sqlwb,isql和其他)的指令,用于在不同的语句中拆分脚本。 所以你不能在SP和函数中使用它(甚至在动态SQL中),只能在脚本中使用它。
虽然我不明白为什么你的SP无法创建,但如果你想从Java,.NET,你需要添加的其他平台运行你的程序
SET NOCOUNT ON
答案 1 :(得分:0)
TempTable不可用
您收到此错误是因为本地临时表仅对创建它的连接可见,并在关闭该连接时被删除。在存储过程中使用GO
结束批处理,从而结束存储过程。
解决方案是使用单个INSERT
查询并使用OUTPUT
子句存储新插入的IDs
:
INSERT INTO MyDBTable (something, something, something)
OUTPUT Inserted.ID INTO #TempTable(NewID)
VALUES (1, 2, @PassInVariable);
将来自ID
的{{1}}替换为来自INSERTED.ID
的正确ID
要多次插入行,您可以使用Tally Table:
MyDBTable
将WITH E1(N) AS(
SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b),
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b),
E8(N) AS(SELECT 1 FROM E4 a CROSS JOIN E4 b),
Tally(N) AS(
SELECT TOP(70000)
ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM E8
)
INSERT INTO MyDBTable(something, something, something)
OUTPUT Inserted.ID INTO #TempTable(NewID)
SELECT
1, 2, @PassInVariable
FROM Tally
替换为您要插入的行数。
答案 2 :(得分:0)
MS SQL中的GO语句释放资源并清理会话;这就是临时表和变量一样消失的原因。
在您的存储过程中或至少上面的SQL脚本中,您不需要go语句。
您在其他脚本中看到的GO语句是为了防止解析器在前一个语句出错后停止执行。它类似于Visual Basic" On Error Resume Next"声明。这样你的脚本将继续执行,直到脚本文件结束。
您将看到GO语句主要用于包含多个事务的脚本文件中;每次交易后都是一个go语句。例如,包含用于不同存储过程的多个CREATE语句的脚本文件。但是在一次交易中,您不想使用GO语句,因为您将在脚本中看到所有变量(包括临时表)。
我不会在你的存储过程中看到需要。
答案 3 :(得分:0)
临时表不可用的原因是存储过程是:
CREATE PROCEDURE sp_MassInsertProcedure
@PassInVariable int
AS
CREATE TABLE #TempTable(OriginalID int IDENTITY(1,1), NewID int);
--These inserts are essentially repeated 70,000 times
INSERT INTO MyDBTable (something, something, something) VALUES (1, 2, @PassInVariable);
INSERT INTO #TempTable(NewID) SELECT SCOPE_IDENTITY();
GO
定义在GO
停止,原因在其他答案中解释。
现在,一些有用的建议:
BEGIN
/ END
块或BEGIN CATCH
/ END TRY
块中。然后对它的存在或结束没有任何含糊之处。OUTPUT
子句。 SCOPE_IDENTITY()
非常安全。但是OUTPUT
更好,通常是推荐的方法。答案 4 :(得分:0)
谢谢大家的答案......我最终得到了以下解决方案:
从调用我的存储过程的脚本中创建了#TempTable
numpy.save
然后在我的存储过程中,我有:
CREATE TABLE #TempTable (OriginalID int IDENTITY(1,1), NewID int);
EXEC sp_InsertMassRecords 777;
我在大约每100个select语句之后重复INSERT / OUTPUT行,并且整个事情成功地运行得非常快!