当存储过程可以由不同的用户同时运行时,是否建议使用临时表?


8

我正在研究一种从活动目录检索objectGUID的存储过程。我将结果存储在临时表中,然后在输出参数中返回该值以用于其他进程。将通过不同的存储过程以及Web应用程序PHP,ASP Classic和ASP.Net调用SP。

我在这里读到(关于临时表):

如果在存储过程中创建,则它们将在存储过程完成时销毁。此外,任何特定临时表的范围都是创建该临时表的会话。表示仅对当前用户可见。多个用户可以创建一个名为#TableX的临时表,并且同时运行的任何查询都不会相互影响-他们将保持自主事务,而这些表保持自主对象。您可能会注意到我的示例临时表名称以“#”符号开头。

听起来我很高兴,但我想获得一些建议,以确保没有我不知道的陷阱。这是SP。

提前致谢。

CREATE PROCEDURE stp_adlookup
@user varchar(100),
@objectGUID varbinary(256) OUTPUT
AS
SET NOCOUNT ON;
DECLARE @qry char(1000)
CREATE TABLE #tmp(
objectGUID nvarchar(256)
)

SET @qry = 'SELECT *
FROM openquery(ADSI, ''
SELECT  objectGUID              
FROM    ''''LDAP://mydomaincontroller.com''''
WHERE sAMAccountName = ''''' + @user + '''''
'')'
INSERT INTO #tmp
EXEC(@qry)
SELECT @objectGUID=CAST(objectGUID as varbinary(256))  FROM #tmp;
DROP TABLE #tmp
SET NOCOUNT OFF;
GO

Answers:


15

是的,即使每个用户在同一时间运行,他们也将获得自己的#temp表副本。

(但是,请勿使用以两个前导英镑/哈希符号表示的全局## temp表。)

但是,为什么这里完全需要一个#temp表?这样的事情应该可以工作(未经测试,因为我附近没有LDAP):

CREATE PROCEDURE dbo.stp_adlookup -- ALWAYS use schema prefix
  @user varchar(100),
  @objectGUID varbinary(256) OUTPUT
AS
BEGIN -- use body wrappers
  SET NOCOUNT ON;

  DECLARE @qry nvarchar(max); -- don't use CHAR for dynamic SQL

  SET @qry = N'SELECT @o = objectGUID
    FROM openquery(ADSI, ''SELECT  objectGUID              
      FROM    ''''LDAP://mydomaincontroller.com''''
      WHERE sAMAccountName = ''''' + @user + ''''''')';

  -- can probably parameterize the above, but those single
  -- quotes are a nightmare. Not sure if they're necessary
  -- but I do not feel like trying to untangle them.

  EXEC sys.sp_executesql @qry, N'@o UNIQUEIDENTIFIER', @o = @objectGUID OUTPUT;

  -- SET NOCOUNT OFF; -- don't do this.
END
GO

8

您应该很好,我们这里有无数的SP,它们每天使用命名为相同且没有任何问题的临时表运行1000次。

这是一个视觉示例。我在SQL2014实例上创建了2个表。一个是从SPID 53创建的,另一个是从SPID 57创建的。这是对象资源管理器中的外观:

在此处输入图片说明

如您所见,尽管它们的“命名”是相同的,但最后,还有一组可爱的字符使表与众不同。唯一的区别是我从不同的查询窗口执行了CREATE语句。这只是一种直观的显示方式。查询#tmp表时,仅查询适用于会话的表。

我会提出一个建议。我对此完全感到内and,正在努力过渡。使用sp_executesql代替EXEC()。亚伦·伯特兰(Aaron Bertrand)将此写为“踢球的坏习惯”之一:

基本上,使用sp_executesql将减少SQL注入的机会,并且执行计划可以重用的机会更大。亚伦在文章中进行了详细介绍,但这是1000英尺高的视图。


5
我只是补充说,为每个过程唯一地命名本地临时表很有用,因为该过程可以从另一个已经创建了具有相同名称的本地临时表的过程中调用。
保罗·怀特9

2

从广义上讲,这样做会很好。存储过程的范围有限,因此即使(示例)3个用户执行相同的存储过程,并且临时表不会混合在一起,他们甚至也不会看到彼此。

只要您不需要与其他会话共享结果,或者不需要用户运行其他进程的Temp表,就可以成为一种完美的选择。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.