Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Khi sử dụng GETDATE () ở nhiều nơi, tốt hơn là sử dụng một biến?

[LƯU Ý:Nếu bạn định từ chối câu trả lời này, vui lòng để lại bình luận giải thích lý do. Nó đã bị từ chối nhiều lần và cuối cùng ypercube (cảm ơn bạn) đã giải thích ít nhất một lý do tại sao. Tôi không thể xóa câu trả lời vì nó đã được chấp nhận, vì vậy bạn cũng có thể giúp cải thiện câu trả lời.]

Theo trao đổi này trên Microsoft, GETDATE() đã chuyển từ không đổi trong một truy vấn sang không xác định trong SQL Server 2005. Khi nhìn lại, tôi không nghĩ điều đó là chính xác. Tôi nghĩ rằng nó hoàn toàn không xác định trước SQL Server 2005 và sau đó bị tấn công vào một thứ gọi là "hằng số thời gian chạy không xác định" kể từ SQL Server 2005 ". Cụm từ sau này thực sự có nghĩa là" hằng số trong một truy vấn ".

(Và GETDATE() được định nghĩa là không xác định rõ ràng và tự hào, không có định nghĩa.)

Than ôi, trong SQL Server, tính không xác định không có nghĩa là một hàm được đánh giá cho mọi hàng. SQL Server thực sự làm cho điều này trở nên phức tạp và không rõ ràng với rất ít tài liệu về chủ đề này.

Trong thực tế, lời gọi hàm được đánh giá khi truy vấn đang chạy thay vì một lần khi truy vấn được biên dịch và giá trị của nó thay đổi mỗi khi nó được gọi. Trên thực tế, GETDATE() chỉ được đánh giá một lần cho mỗi biểu thức nơi nó được sử dụng - tại thời gian thực thi thay vì thời gian biên dịch . Tuy nhiên, Microsoft đặt rand()getdate() vào một danh mục đặc biệt, được gọi là các hàm hằng thời gian chạy không xác định. Ngược lại, Postgres không nhảy qua các vòng như vậy, nó chỉ gọi các hàm có giá trị không đổi khi được thực thi là "ổn định".

Bất chấp nhận xét của Martin Smith, tài liệu SQL Server đơn giản là không rõ ràng về vấn đề này - GETDATE() được mô tả là cả "không xác định" và "hằng số thời gian chạy không xác định", nhưng thuật ngữ đó không thực sự được giải thích. Ví dụ, một nơi tôi đã tìm thấy thuật ngữ, các dòng tiếp theo trong tài liệu nói rằng không sử dụng các hàm không xác định trong các truy vấn con. Đó sẽ là lời khuyên ngớ ngẩn cho "hằng số thời gian chạy không xác định".

Tôi khuyên bạn nên sử dụng một biến với một hằng số ngay cả trong một truy vấn, để bạn có một giá trị nhất quán. Điều này cũng làm cho ý định khá rõ ràng:Bạn muốn một giá trị duy nhất bên trong truy vấn. Trong một truy vấn duy nhất, bạn có thể làm điều gì đó như:

select . . . 
from (select getdate() as now) params cross join
     . . . 

Thực ra, đây là một gợi ý mà nên chỉ đánh giá một lần trong truy vấn, nhưng có thể có ngoại lệ. Sự nhầm lẫn nảy sinh vì getdate() trả về cùng một giá trị trên tất cả các hàng khác nhau - nhưng nó có thể trả về các giá trị khác nhau trong các cột khác nhau. Mỗi biểu thức với getdate() được đánh giá độc lập. Điều này hiển nhiên nếu bạn chạy:

select rand(), rand()
from (values (1), (2), (3)) v(x);

Trong một thủ tục được lưu trữ, bạn sẽ muốn có một giá trị duy nhất trong một biến. Điều gì xảy ra nếu thủ tục đã lưu trữ được chạy khi nửa đêm trôi qua và ngày thay đổi? Điều đó có tác động gì đến kết quả?

Đối với hiệu suất, tôi đoán rằng việc tra cứu ngày / giờ là tối thiểu và đối với một truy vấn xảy ra một lần cho mỗi biểu thức khi truy vấn bắt đầu chạy. Đây thực sự không phải là một vấn đề về hiệu suất, mà là một vấn đề về tính nhất quán của mã.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Khi nào sử dụng EXCEPT thay vì NOT EXISTS trong Transact SQL?

  2. 5 cách đếm số lượng bảng do người dùng xác định trong cơ sở dữ liệu máy chủ SQL

  3. Cách tìm tên cột cho tất cả các bảng trong tất cả cơ sở dữ liệu trong SQL Server

  4. Cách tìm định dạng ngày được sử dụng trong phiên hiện tại trong SQL Server (T-SQL)

  5. Làm cách nào để đặt biến từ một truy vấn SQL?