2011-01-28 35 views
183

Tôi có đoạn mã sau vào một trong Sql (2008) lưu Procs của tôi mà thực hiện hoàn toàn tốt đẹp:SQL Server SELECT INTO @variable?

CREATE PROCEDURE [dbo].[Item_AddItem] 
     @CustomerId uniqueidentifier, 
     @Description nvarchar(100), 
     @Type int, 
     @Username nvarchar(100), 
    AS 
    BEGIN 

     DECLARE @TopRelatedItemId uniqueidentifier; 
     SET @TopRelatedItemId = 
     (
      SELECT top(1) RelatedItemId 
      FROM RelatedItems 
      WHERE CustomerId = @CustomerId 
     ) 

     DECLARE @TempItem TABLE 
     (
      ItemId uniqueidentifier, 
      CustomerId uniqueidentifier, 
      Description nvarchar(100), 
      Type int, 
      Username nvarchar(100), 
      TimeStamp datetime 
     ); 

     INSERT INTO Item 
     OUTPUT INSERTED.* INTO @TempItem 
     SELECT NEWID(), @CustomerId, @Description, @Type, @Username, GETDATE() 

     SELECT 
      ItemId, 
      CustomerId, 
      @TopRelatedItemId, 
      Description, 
      Type, 
      Username, 
      TimeStamp 
     FROM 
      @TempItem 
END 
GO 

Vậy câu hỏi cho các bạn được là có một khả năng để làm điều gì đó dọc theo dòng:

DECLARE @TempCustomer TABLE 
(
    CustomerId uniqueidentifier, 
    FirstName nvarchar(100), 
    LastName nvarchar(100), 
    Email nvarchar(100) 
); 
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
INTO 
    @TempCustomer 
FROM 
    Customer 
WHERE 
    CustomerId = @CustomerId 

Để tôi có thể sử dụng lại dữ liệu này từ bộ nhớ trong các câu sau đây? SQL Server ném một phù hợp với các tuyên bố trên, tuy nhiên tôi không muốn phải tạo các biến riêng biệt và khởi tạo mỗi một trong số họ thông qua một tuyên bố SELECT riêng biệt chống lại cùng một bảng .... UGH !!!

Bất kỳ đề xuất nào về cách đạt được điều gì đó dọc theo dòng mà không có nhiều truy vấn đối với cùng một bảng?

+1

"để tạo các biến riêng biệt và khởi tạo từng biến trong số đó thông qua câu lệnh SELECT riêng biệt" - tại sao bạn cần thực hiện điều đó? 'khai báo @t table' một lần, và nếu bạn cần tái sử dụng nó, hãy bật' DELETE @ TempCustomer' trước khi chèn vào nó một lần nữa – RichardTheKiwi

Trả lời

165

Bạn không thể CHỌN .. INTO .. ​​TABLE VARIABLE. Điều tốt nhất bạn có thể làm là tạo ra nó trước, sau đó chèn vào nó. Đoạn mã thứ 2 của bạn phải là

DECLARE @TempCustomer TABLE 
(
    CustomerId uniqueidentifier, 
    FirstName nvarchar(100), 
    LastName nvarchar(100), 
    Email nvarchar(100) 
); 
INSERT INTO 
    @TempCustomer 
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
FROM 
    Customer 
WHERE 
    CustomerId = @CustomerId 
+4

Nên lưu ý rằng điều này cũng hoạt động tốt trong bối cảnh CTE. Bazinga! –

+2

Bất cứ ai cũng có câu trả lời là * tại sao * người ta không thể chọn biến bảng như bạn có thể với một bảng tạm thời thực sự? – KSwift87

13

Dường như cú pháp của bạn hơi lệch. Này có một số good examples

DECLARE @TempCustomer TABLE 
(
    CustomerId uniqueidentifier, 
    FirstName nvarchar(100), 
    LastName nvarchar(100), 
    Email nvarchar(100) 
); 
INSERT @TempCustomer 
SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
FROM 
    Customer 
WHERE 
    CustomerId = @CustomerId 

Rồi sau

SELECT CustomerId FROM @TempCustomer 
2

Âm thanh như bạn muốn bảng temp. http://www.sqlteam.com/article/temporary-tables

Lưu ý rằng #TempTable có sẵn trong suốt SP của bạn.

Lưu ý ## TempTable khả dụng cho tất cả.

+2

## temptable - cho đến khi chủ sở hữu (tác giả) xóa nó hoặc bị ngắt kết nối – RichardTheKiwi

+3

Tôi không muốn bảng tạm thời. Bảng tạm thời đắt và chậm. Tôi chỉ muốn giữ một chút dữ liệu cho một bản ghi cụ thể trong một khoảng thời gian ngắn và làm cho nó có sẵn cho nhiều câu lệnh sql, mà không cần tra cứu tiếp theo. Kể từ khi biến Table có phạm vi trong proc được lưu trữ mà họ đã được xác định trong, họ là giải pháp hoàn hảo để lưu trữ dữ liệu luppled cho rằng một proc gọi ... – bleepzter

+3

Tôi cũng quên đề cập đến rằng DB cư trú trong Azure .... tôi don không muốn giới thiệu một mớ hỗn độn trong việc quản lý các bảng tạm thời. – bleepzter

21

bạn có thể làm điều này:

SELECT 
    CustomerId, 
    FirstName, 
    LastName, 
    Email 
INTO #tempCustomer 
FROM 
    Customer 
WHERE 
    CustomerId = @CustomerId 

sau đó

SELECT CustomerId FROM #tempCustomer 

bạn không cần phải khai báo cấu trúc của #tempCustomer

+3

@webturner Không có điểm nào là đúng. Bảng tạm thời không nằm ngoài phạm vi của các biến proc và bảng không còn là "bộ nhớ chỉ" hơn các bảng tạm thời. –

+0

@MartinSmith Tôi đã sửa chữa, nhận xét đã bị xóa. –

+3

Đừng quên thêm 'DROP TABLE # tempCustomer' khi' # tempCustomer' không cần dùng nữa nếu không lựa chọn tiếp theo sẽ gây ra lỗi '#tempCustomer already exist' – ViRuSTriNiTy

384

Nếu bạn muốn chỉ đơn giản là gán một số biến cho sau này sử dụng, bạn có thể thực hiện chúng trong một lần chụp với một thứ gì đó dọc theo các dòng sau:

declare @var1 int,@var2 int,@var3 int; 

select 
    @var1 = field1, 
    @var2 = field2, 
    @var3 = field3 
from 
    table 
where 
    condition 

Nếu đó là loại điều bạn đang sau

+1

imho câu trả lời hay nhất, nhưng điều gì xảy ra nếu kết quả là nhiều hơn hơn một? – capitano666

+0

Nếu kết quả nhiều hơn một, bạn sẽ nhận được một trong các giá trị có sẵn. Điều đó có thể làm cho một câu đố thú vị! Xem https://www.mssqltips.com/sqlservertip/1888/when-to-use-set-vs-select-when-assigning-values-to-variables-in-sql-server – Smandoli

+5

Để buộc truy vấn trả về sử dụng hàng đơn SELECT TOP 1 – Adrian

-1
"SELECT * 
    INTO 
    @TempCustomer 
FROM 
    Customer 
WHERE 
    CustomerId = @CustomerId" 

có nghĩa là tạo ra một @tempCustomer tablevariable mới và chèn dữ liệu từ khách hàng. Bạn đã tuyên bố nó ở trên nên không cần phải khai báo nữa. Tốt hơn để đi với

INSERT INTO @tempCustomer SELECT * FROM Customer 
+1

Nó không hoạt động. Bạn vẫn cần khai báo biến bảng trước. –

Các vấn đề liên quan