Máy chủ SQL CHỌN VÀO @variable?


250

Tôi có đoạn mã sau trong một trong các Procs được lưu trữ Sql (2008) của tôi, nó thực thi hoàn toàn tốt:

    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ì vậy, câu hỏi cho các bạn là có khả năng để làm một cái 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 đưa ra một sự phù hợp với câu lệnh 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 từng biến trong số chúng thông qua một câu lệnh CHỌN riêng biệt trong cùng một bảng .... UGH !!!

Bất kỳ đề xuất nào về cách đạt được một cái 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ố chúng thông qua một câu lệnh CHỌN riêng biệt" - tại sao bạn cần phải làm điều đó? declare @t tablemột lần và nếu bạn cần sử dụng lại, hãy bắn một lần DELETE @TempCustomertrước khi chèn lại
RichardTheKiwi

Câu trả lời:


204

Bạn không thể CHỌN .. VÀO .. MỘT BIỂU ĐỒ BẢNG. Điều tốt nhất bạn có thể làm là tạo 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

5
Cần lưu ý rằng điều này chỉ hoạt động tốt trong bối cảnh CTE là tốt. Bazeda!
Michael Krauklis

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

504

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

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 theo đuổi


1
Imho trả lời tốt nhất, nhưng điều gì xảy ra nếu kết quả nhiều hơn một?
capitano666

Nếu kết quả là 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 mssqltips.com/sqlservertip/1888/ Ấn
Smandoli

8
Để buộc truy vấn trả về một hàng đơn, hãy sử dụng CHỌN HÀNG ĐẦU 1
Adrian

1
@Adrian Có, truy vấn trên giả định bạn đã chọn một hàng. Bạn cũng có thể sử dụng các hàm sắp xếp và tổng hợp nếu bạn muốn logic lạ mắt hơn.
dougajmcdonald

1
Trong trường hợp nếu bạn không sử dụng loại cơ sở dữ liệu mà OP đang sử dụng, không phải tất cả đều hỗ trợ TOP 1 như Adrian đã đề cập. SQL Server / MS Access sử dụng TOP, MySQL sử dụng LIMIT và Oracle sử dụng ROWNUM. Xem w3schools.com/sql/sql_top.asp để biết thêm thông tin.
Tyler

33

bạn có thể làm được việc 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 Cả hai điểm đó đều không đúng. Các bảng tạm thời không nằm trong phạm vi của các biến và bảng không có nhiều "chỉ bộ nhớ" hơn các bảng tạm thời.
Martin Smith

7
Đừng quên thêm DROP TABLE #tempCustomerkhi #tempCustomerkhông cần thiết nữa nếu không lựa chọn tiếp theo sẽ gây ra #tempCustomer already existslỗi
ViRuSTriNiTy

15

Có vẻ như cú pháp của bạn là hơi ra. Điều này có một số ví dụ tốt

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

Sau đó

SELECT CustomerId FROM @TempCustomer

2

Âm thanh như bạn muốn bảng tạm thời. http://www.sqlteam.com/article/t tạm-tables

Lưu ý rằng #TempTable có sẵn trong toàn bộ SP của bạn.

Lưu ý ## TempTable có sẵn cho tất cả.


2
## cám dỗ - cho đến khi chủ sở hữu (người tạo) xóa nó hoặc bị ngắt kết nối
RichardTheKiwi

4
Tôi không muốn bảng tạm thời. Bảng Temp là đắt tiền 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 nhỏ 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. Do Biến Bảng có phạm vi trong phạm vi lưu trữ được xác định, chúng là giải pháp hoàn hảo để lưu trữ dữ liệu được chia sẻ cho một cuộc gọi Proc được lưu trữ đó ...
bleepzter

3
Tôi cũng quên đề cập rằng DB nằm trong Azure .... Tôi 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

Bảng biến là cách để đi. khai báo @varTable Table (....)
ARLibertarian

1

Tôi thấy câu hỏi của bạn đang tìm kiếm một giải pháp cho cùng một vấn đề; và những gì các câu trả lời khác không chỉ ra là một cách sử dụng một biến để thay đổi tên của bảng cho mỗi lần thực hiện thủ tục của bạn ở dạng cố định, không phải là tạm thời.

Cho đến nay những gì tôi làm là nối toàn bộ mã SQL với các biến để sử dụng. Như thế này:

declare @table_name as varchar(30)
select @table_name = CONVERT(varchar(30), getdate(), 112)
set @table_name = 'DAILY_SNAPSHOT_' + @table_name

EXEC('
        SELECT var1, var2, var3
        INTO '+@table_name+'
        FROM my_view
        WHERE string = ''Strings must use double apostrophe''
    ');

Tôi hy vọng nó có ích, nhưng nó có thể cồng kềnh nếu mã quá lớn, vì vậy nếu bạn đã tìm thấy một cách tốt hơn, hãy chia sẻ!


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

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

INSERT INTO @tempCustomer SELECT * FROM Customer

4
Nó không hoạt động. Bạn vẫn cần khai báo biến bảng trước.
Johan Boulé
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.