Có nên sử dụng bảng tạm thời khi quy trình được lưu trữ có thể được chạy đồng thời bởi những người dùng khác nhau không?


8

Tôi đang làm việc trên một thủ tục được lưu trữ để lấy objectGUID từ thư mục hoạt động. Tôi đang lưu trữ kết quả trong một bảng tạm thời và sau đó trả về giá trị trong một tham số đầu ra để sử dụng với các quy trình khác. SP sẽ được gọi từ các thủ tục được lưu trữ khác nhau cũng như các ứng dụng web PHP, ASP Classic và ASP.Net.

Tôi đọc TẠI ĐÂY rằng (liên quan đến bảng tạm thời):

Nếu được tạo bên trong một thủ tục được lưu trữ, chúng sẽ bị hủy khi hoàn thành thủ tục được lưu trữ. Hơn nữa, phạm vi của bất kỳ bảng tạm thời cụ thể nào là phiên mà nó được tạo; có nghĩa là nó chỉ hiển thị cho người dùng hiện tại. Nhiều người dùng có thể tạo một bảng tạm thời có tên #TableX và mọi truy vấn chạy đồng thời sẽ không ảnh hưởng đến nhau - họ sẽ duy trì các giao dịch tự trị và các bảng sẽ vẫn là các đối tượng tự trị. Bạn có thể nhận thấy rằng tên bảng tạm thời mẫu của tôi bắt đầu bằng dấu "#".

Nghe có vẻ như tôi rất tốt để đi nhưng tôi muốn nhận được một lời khuyên để đảm bảo rằng không có bất kỳ vấn đề nào mà tôi không biết. Đây là SP.

Cảm ơn trước.

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

Câu trả lời:


15

Có, mỗi người dùng sẽ nhận được bản sao của bảng #temp của riêng họ, ngay cả khi họ chạy cùng một lúc.

(Tuy nhiên, không sử dụng bảng ## temp toàn cầu, được biểu thị bằng hai dấu thăng / băm hàng đầu.)

Nhưng tại sao bạn lại cần một bảng #temp ở đây? Một cái gì đó như thế này sẽ hoạt động (chưa được kiểm tra, vì tôi không có LDAP ở bất cứ đâu gần tôi):

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

Bạn sẽ ổn thôi, chúng tôi có vô số SP ở đây chạy 1000 lần một ngày với các bảng tạm thời được đặt tên giống nhau và không có bất kỳ vấn đề nào.

Đây là một ví dụ trực quan. Tôi đã tạo 2 bảng trên phiên bản SQL2014 của mình. Một cái được tạo từ SPID 53, cái kia từ SPID 57. Đây là giao diện trong Object Explorer:

nhập mô tả hình ảnh ở đây

Như bạn có thể thấy, mặc dù chúng được 'đặt tên' giống nhau, nhưng cuối cùng, có một bộ ký tự đáng yêu làm cho các bảng khác nhau. Sự khác biệt duy nhất là tôi đã thực thi các câu lệnh CREATE từ các cửa sổ truy vấn khác nhau. Đây chỉ là một cách trực quan để hiển thị nó. Khi bạn truy vấn bảng #tmp, bạn chỉ truy vấn bảng áp dụng cho phiên của bạn.

Tôi sẽ đưa ra một đề nghị, mặc dù. Đó là điều mà tôi hoàn toàn có lỗi và tôi đang làm việc để chuyển sang. Sử dụng sp_executesqlthay vì EXEC(). Aaron Bertrand đã viết điều này như là một trong những 'Thói quen xấu để đá':

Về cơ bản, sử dụng sp_executesql sẽ làm giảm cơ hội tiêm SQL và có nhiều khả năng kế hoạch thực hiện có thể được sử dụng lại. Aaron đi sâu vào chi tiết hơn trong bài viết, nhưng đó là góc nhìn 1000 feet.


5
Tôi chỉ nói thêm rằng có thể hữu ích khi đặt tên các bảng tạm thời cục bộ duy nhất cho mỗi thủ tục, bởi vì thủ tục có thể được gọi từ một thủ tục khác đã tạo một bảng tạm thời cục bộ có cùng tên.
Paul White 9

2

từ một nghĩa rộng, bạn sẽ ổn khi làm theo cách này. Các thủ tục được lưu trữ có phạm vi hạn chế, do đó, mặc dù (ví dụ) 3 người dùng thực hiện cùng một quy trình được lưu trữ và các bảng tạm thời sẽ không kết hợp với nhau, họ thậm chí sẽ không nhìn thấy nhau.

Miễn là bạn không cần chia sẻ kết quả với một phiên khác hoặc người dùng đang chạy một bảng quy trình khác có thể là một cách hoàn hảo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.