我知道这可能是一个新手问题,但是我在使用SQL Server理解表变量的范围时遇到了一些问题,与在简单查询中执行的相关应用程序(没有存储过程,没有功能)。
Here,我可以读到:
表变量的行为类似于局部变量。它有一个明确的定义 范围。这是函数,存储过程或批处理 声明在。
我使用Knex客户端的raw()
功能在Node.js应用程序中使用SQL Server。我认为Knex使用node-mssql包并最终使用Tedious来执行请求。初始化Knex客户端时会创建连接池。
因此,假设我在事务中使用Knex运行此查询:
await knex.raw(`
DECLARE @emailIdsToDelete TABLE(id int NOT NULL);
INSERT INTO @emailIdsToDelete
SELECT id
FROM ...;
DELETE organisations_emails
FROM @emailIdsToDelete etd
INNER JOIN ...;
DELETE emails
FROM @emailIdsToDelete etd
INNER JOIN ...;
`);
此处@emailIdsToDelete
的范围是什么?
一旦这个特定的查询结束(这是我想要的),是否会删除该表,或者只要连接池中的连接处于活动状态,它是否会存在?
如何确保该表仅存在于该特定请求的范围内?
我应该在最后使用“GO
”关键字将其删除吗?
答案 0 :(得分:1)
为了充分披露,我有点喜欢行使明确的控制权,而不是依赖代码“应该做什么”或“通常做什么”。叫我偏执狂。
也就是说,发出一个GO来明确地结束你的批处理将确保你的表变量消失。
编辑:但是alroc是对的。我在思考SSMS脚本,而不是第三方调用。 GO可能没用。当然,您的另一个选择是使用临时表,并再次对其进行明确控制。
CREATE TABLE #emailIdsToDelete (id int NOT NULL);
...<logic>...
DROP TABLE #emailIdsToDelete;
答案 1 :(得分:1)
https://docs.microsoft.com/en-us/sql/t-sql/language-elements/sql-server-utilities-statements-go
GO不是Transact-SQL语句;它是sqlcmd和osql实用程序以及SQL Server Management Studio代码编辑器识别的命令。
IOW,在你的陈述中包括GO
充其量只是毫无意义,最坏的情况下会抛出错误。在您提供的代码中,您的表变量的范围将在您的请求完成后终止。
在这种情况下,表变量的范围是您在raw()
函数中提交给SQL Server的批处理,当查询完成时,其中的所有内容都将超出范围。来自http://technet.microsoft.com/en-us/library/ms187953(v=sql.105).aspx
变量的范围是可以引用变量的Transact-SQL语句的范围。变量的范围从声明它的位置开始持续到声明它的批处理或存储过程的结束。