Khai báo biến cho một chuỗi truy vấn


92

Tôi đã tự hỏi liệu có cách nào để thực hiện việc này trong MS SQL Server 2005 không:

  DECLARE @theDate varchar(60)
  SET @theDate = '''2010-01-01'' AND ''2010-08-31 23:59:59'''

  SELECT    AdministratorCode, 
            SUM(Total) as theTotal, 
            SUM(WOD.Quantity) as theQty, 
            AVG(Total) as avgTotal, 
            (SELECT SUM(tblWOD.Amount)
                FROM tblWOD
                JOIN tblWO on tblWOD.OrderID = tblWO.ID
                WHERE tblWO.Approved = '1' 
                AND tblWO.AdministratorCode = tblWO.AdministratorCode
                AND tblWO.OrderDate BETWEEN @theDate
            )
 ... etc

Đây có phải là có thể làm gì?


Câu trả lời:


96

Có thể, nhưng nó yêu cầu sử dụng SQL động.
Tôi khuyên bạn nên đọc Lời nguyền và phước lành của SQL động trước khi tiếp tục ...

DECLARE @theDate varchar(60)
SET @theDate = '''2010-01-01'' AND ''2010-08-31 23:59:59'''

DECLARE @SQL VARCHAR(MAX)  
SET @SQL = 'SELECT AdministratorCode, 
                   SUM(Total) as theTotal, 
                   SUM(WOD.Quantity) as theQty, 
                   AVG(Total) as avgTotal, 
                  (SELECT SUM(tblWOD.Amount)
                     FROM tblWOD
                     JOIN tblWO on tblWOD.OrderID = tblWO.ID
                    WHERE tblWO.Approved = ''1''
                      AND tblWO.AdministratorCode = tblWO.AdministratorCode
                      AND tblWO.OrderDate BETWEEN '+ @theDate +')'

EXEC(@SQL)

SQL động chỉ là một câu lệnh SQL, được tạo thành một chuỗi trước khi được thực thi. Vì vậy, việc nối chuỗi thông thường xảy ra. SQL động là bắt buộc bất cứ khi nào bạn muốn làm điều gì đó trong cú pháp SQL không được phép, như:

  • một tham số duy nhất để biểu thị danh sách giá trị được phân tách bằng dấu phẩy cho mệnh đề IN
  • một biến đại diện cho cả giá trị và cú pháp SQL (IE: ví dụ bạn đã cung cấp)

EXEC sp_executesql cho phép bạn sử dụng các tham số ràng buộc / chuẩn bị sẵn sàng để bạn không cần phải lo lắng về việc thoát các dấu ngoặc kép / vv cho các cuộc tấn công SQL injection.


Tôi nghĩ đây là câu trả lời chính xác nhất. Gần đây, tôi cũng đang sử dụng SQL Server 2005 và việc sử dụng một biến để thay thế chuỗi truy vấn như OP muốn là không thể (tạo ra lỗi cú pháp). Các biến không thể bao gồm cả cú pháp và kiểu dữ liệu, như @Ponies nói. SQL động là cách để xây dựng truy vấn trong SQL Server thông qua chuỗi. Chỉ cần nhớ cẩn thận về các trích dẫn và loại của bạn! Chuỗi mà bạn thực thi yêu cầu một số kiểu, như datetime hoặc int, được chuyển đổi hoặc ép kiểu để nối chuỗi.
RoboBear

52
DECLARE @theDate DATETIME
SET @theDate = '2010-01-01'

Sau đó, thay đổi truy vấn của bạn để sử dụng logic này:

AND 
(
    tblWO.OrderDate > DATEADD(MILLISECOND, -1, @theDate) 
    AND tblWO.OrderDate < DATEADD(DAY, 1, @theDate)
)

2
Treo lên. Đó không thể là câu trả lời nếu câu hỏi hiển thị rõ ràng hai ngày khác nhau. Cuối cùng thì bạn đã viết mã nó như thế nào @StealthRT? Đâu là ngày '2010-08-31' trong câu trả lời? Ngoài ra, câu hỏi hỏi rõ ràng liệu bạn có thể sử dụng các biến DECLARE để thay thế mã thành một câu lệnh SELECT khác hay không. Câu trả lời thích hợp là dưới đây.
Fandango68

2

Sử dụng EXEC

Bạn có thể sử dụng ví dụ sau để xây dựng câu lệnh SQL.

DECLARE @sqlCommand varchar(1000)
DECLARE @columnList varchar(75)
DECLARE @city varchar(75)
SET @columnList = 'CustomerID, ContactName, City'
SET @city = '''London'''
SET @sqlCommand = 'SELECT ' + @columnList + ' FROM customers WHERE City = ' + @city
EXEC (@sqlCommand)

Sử dụng sp_executesql

Với việc sử dụng phương pháp này, bạn có thể đảm bảo rằng các giá trị dữ liệu được chuyển vào truy vấn là kiểu dữ liệu chính xác và sử dụng nhiều dấu ngoặc kép hơn.

DECLARE @sqlCommand nvarchar(1000)
DECLARE @columnList varchar(75)
DECLARE @city varchar(75)
SET @columnList = 'CustomerID, ContactName, City'
SET @city = 'London'
SET @sqlCommand = 'SELECT ' + @columnList + ' FROM customers WHERE City = @city'
EXECUTE sp_executesql @sqlCommand, N'@city nvarchar(75)', @city = @city

Tài liệu tham khảo


1

Tôi sẽ chỉ ra rằng trong bài viết được liên kết trong câu trả lời được đánh giá cao nhất Lời nguyền và phước lành của SQL động , tác giả tuyên bố rằng câu trả lời là không sử dụng SQL động. Cuộn gần như đến cuối để xem điều này.

Từ bài viết: "Phương pháp đúng là giải nén danh sách thành một bảng với một hàm do người dùng xác định hoặc một thủ tục được lưu trữ."

Tất nhiên, khi danh sách nằm trong một bảng, bạn có thể sử dụng một phép nối. Tôi không thể bình luận trực tiếp về câu trả lời được xếp hạng cao nhất, vì vậy tôi chỉ thêm nhận xét này.


Điều này không cung cấp câu trả lời cho câu hỏi. Một khi bạn có đủ danh tiếng, bạn sẽ có thể nhận xét về bất kỳ bài đăng nào ; thay vào đó, cung cấp câu trả lời không yêu cầu người hỏi làm rõ . - Từ đánh giá
Sam M

Cảm ơn Sam. Tôi sẽ cập nhật nhận xét của mình với các chi tiết sau khi tôi thực hiện những gì Erland Sommarskog đề xuất. Tôi cũng sẽ gọi tên anh ấy vì anh ấy xứng đáng được ghi nhận cho câu trả lời.
DavidG
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.