2010-11-15 45 views
7

Tôi gặp phải một vấn đề thú vị hiện nay. Tôi đã thay đổi một thủ tục lưu trữ và đặt một tuyên bố chọn vào cuối cùng. Nó có nghĩa là tạm thời và chỉ để làm việc với dữ liệu. Tôi đã ngạc nhiên khi phát hiện ra rằng tuyên bố đã được lưu lại và đang thực hiện bất cứ khi nào SP chạy.Các câu lệnh sau END trong thủ tục lưu sẵn

SET ANSI_NULLS ON 
GO 

-- Comments usually go here and are saved as part of the SP 
ALTER PROCEDURE [dbo].[MySP] 
    @param INT 
AS 
BEGIN 
    --Your normal SQL statements here 
END 

--You can also add SQL statements here 
select * from LargeTable 

--You have access to the params 
select @param 

Có nghĩa là mọi thứ được lưu, không chỉ những gì ở bên trong BEGIN/END, nếu không các nhận xét và SET ANSI_NULLS, v.v. sẽ biến mất. Tôi hơi bối rối với những gì bắt đầu từ đâu, vì vậy tôi có một số câu hỏi:

  1. SET ANSI_NULLS được lưu như một phần của SP. Tôi đã xác nhận rằng mỗi SP có giá trị riêng. Làm thế nào để SQL Server biết để lưu này như là một phần của SP vì nó không được tham chiếu trước đây? Liệu nó có quét toàn bộ trạng thái môi trường hiện tại không, sau đó khi ALTER PROCEDURE chạy nó lưu trạng thái (chỉ có thể các giá trị không mặc định)?
  2. Dường như BEGIN/END là tùy chọn và không có ý nghĩa nội tại. Tại sao họ thậm chí bao gồm sau đó? Họ đưa ra một cảm giác sai phạm vi không tồn tại. Dường như với tôi không có BEGIN/END và GO ở cuối sẽ có ý nghĩa nhất.
+1

BEGIN/END được sử dụng cho phạm vi, như chứa nhiều câu lệnh trong một IF/WHILE/etc. Thành thật mà nói, TSQL là tàn nhẫn để làm việc với so với PLSQL - đó là cấu trúc/tổ chức hơn trong cách nó sử dụng BEGIN/END, và sử dụng dấu chấm phẩy để chấm dứt dòng. Giống như cách TSQL yêu cầu một dấu chấm phẩy trước một WITH/CTE nếu bạn khai báo biến trước khi nó ...:/Bất cứ ai có kinh nghiệm ngôn ngữ dựa trên C đều có thể được cung cấp PLSQL và có thể đọc nó. Không thể nói điều đó đối với TSQL ... –

+0

@OMG - Vậy trường hợp này có phạm vi "phạm vi" nào? Điều duy nhất tôi có thể tưởng tượng là nếu bạn khai báo một biến bên trong BEGIN/END, nó không có sẵn bên ngoài. Tại sao bạn lại đặt câu lệnh SQL ở bên ngoài; tại sao bạn không đặt mọi thứ bên ngoài và không có BEGIN/END? –

+1

Ví dụ là hợp lệ, tôi không nói nó là sapient;) –

Trả lời

5

ANSI NULLS và QUOTED IDENTIFIERS được lưu trữ dưới dạng thuộc tính siêu dữ liệu của mã thủ tục được lưu trữ. Bạn có thể xem lại các cài đặt này qua

select * from sys.sql_modules 

Khi lưu một thủ tục, các thuộc tính này được đặt thành bất kỳ kết nối nào mà quy trình được lưu. Điều này có thể dẫn đến những mâu thuẫn khó chịu, vì vậy hãy cảnh giác.

Đối với BEGIN/END, chính xác như @bobs nói - chúng biểu thị các khối mã, chúng không biểu thị sự bắt đầu và kết thúc của mã thủ tục được lưu trữ. (Chức năng, vâng, thủ tục, không.) Như bạn nói, no BEGIN/END and a GO at the end would make the most sense là cách tôi đã làm nó trong nhiều năm.

Về mặt kỹ thuật, SQL sẽ (cố gắng) lưu mọi thứ trong một lô như một phần của quy trình được lưu trữ - nghĩa là tất cả văn bản bạn gửi, như được chia nhỏ bởi câu lệnh GO (nếu có). Nếu bạn đã mắc một câu lệnh RETURN ngay trước truy vấn đặc biệt của bạn, chúng sẽ được bao gồm trong mã nhưng không bao giờ chạy.

+0

+1 cho 'sys.sql_modules' và hàm DO sử dụng' BEGIN/END'. Chỉ có vấn đề với 'GO' ở cuối là nó không được tạo ra bởi các tùy chọn sửa đổi, do đó, lần sau nó không có. Nhưng ít nhất thì 'BEGIN/END' cũng không có. –

5

BEGIN...END xác định một khối mã. Nó không xác định sự bắt đầu và kết thúc của một kịch bản hoặc thủ tục. Nhưng, tôi đồng ý nó có thể gây nhầm lẫn.

Cài đặt SET QUOTED_IDENTIFIER và SET ANSI_NULLS được lưu nhưng không được cài đặt khác. Kiểm tra Khả năng tương tác here để biết thêm thông tin.

+0

Điều đó trả lời câu hỏi đầu tiên của tôi, cảm ơn: 'Cơ sở dữ liệu lưu các thiết lập của cả SET QUOTED_IDENTIFIER và SET ANSI_NULLS khi một thủ tục Transact-SQL được tạo hoặc sửa đổi ... Các tùy chọn SET khác, chẳng hạn như SET ARITHABORT, SET ANSI_WARNINGS, hoặc SET ANSI_PADDINGS không được lưu khi thủ tục được tạo hoặc sửa đổi.Nếu logic của quy trình phụ thuộc vào một cài đặt cụ thể, bao gồm câu lệnh SET ở đầu thủ tục để đảm bảo cài đặt thích hợp.' –

1

bao quanh một loạt các Transact-SQL báo cáo để cho một nhóm các báo cáo Transact-SQL có thể được thực thi. BEGINEND là từ khóa ngôn ngữ kiểm soát luồng.

Khi SET ANSI_NULLSON, một tuyên bố SELECT sử dụng WHERE tên_cột = NULL lợi nhuận bằng không hàng ngay cả khi có giá trị null trong column_name. Câu lệnh SELECT sử dụng WHERE column_name <>NULL trả về các hàng bằng không ngay cả khi có các giá trị không trống trong column_name.

Khi SET ANSI_NULLS bị TẮT, các toán tử so sánh bằng (=) và Không bằng với (<>) không tuân theo tiêu chuẩn ISO. Câu lệnh SELECT sử dụng WHERE column_name = NULL trả về các hàng có giá trị null trong cột_name. Câu lệnh SELECT sử dụng WHERE column_name <>NULL trả về các hàng có giá trị không trống trong cột. Ngoài ra, một câu lệnh SELECT sử dụng WHERE column_name <> XYZ_value trả về tất cả các hàng không phải là XYZ_value và không phải là NULL.

Khi SET ANSI_NULLSON, tất cả so sánh với giá trị null được đánh giá là UNKNOWN. Khi SET ANSI_NULLSOFF, so sánh tất cả dữ liệu dựa trên giá trị rỗng được đánh giá là TRUE nếu giá trị dữ liệu là NULL. Nếu SET ANSI_NULLS không được chỉ định, cài đặt của tùy chọn ANSI_NULLS của cơ sở dữ liệu hiện tại sẽ được áp dụng. Để biết thêm thông tin về tùy chọn cơ sở dữ liệu ANSI_NULLS, hãy xem ALTER DATABASE (Giao dịch-SQL) và Tùy chọn cơ sở dữ liệu thiết lập.

SET ANSI_NULLS ON chỉ ảnh hưởng đến so sánh nếu một trong các toán hạng của so sánh là biến số NULL hoặc chữ số NULL. Nếu cả hai bên của so sánh là các cột hoặc biểu thức phức, thì cài đặt này không ảnh hưởng đến so sánh.

Để tập lệnh hoạt động như dự kiến, bất kể tùy chọn cơ sở dữ liệu ANSI_NULLS hoặc cài đặt SET ANSI_NULLS, hãy sử dụng IS NULLIS NOT NULL so sánh có thể chứa giá trị null.

SET ANSI_NULLS phải được đặt thành BẬT để thực hiện truy vấn được phân phối.

SET ANSI_NULLS cũng phải BẬT khi bạn đang tạo hoặc thay đổi chỉ mục trên các cột được tính toán hoặc chế độ xem được lập chỉ mục. Nếu SET ANSI_NULLSOFF, bất kỳ số CREATE, UPDATE, INSERTDELETE câu lệnh trên bảng có chỉ mục trên cột được tính toán hoặc chế độ xem được lập chỉ mục sẽ không thành công. SQL Server sẽ trả về lỗi liệt kê tất cả các tùy chọn SET vi phạm các giá trị được yêu cầu. Ngoài ra, khi bạn thực thi câu lệnh SELECT, nếu SET ANSI_NULLSOFF, SQL Server sẽ bỏ qua các giá trị chỉ mục trên cột hoặc chế độ xem được tính toán và giải quyết thao tác chọn như thể không có chỉ mục như vậy trên bảng hoặc chế độ xem.

+0

Thông tin tốt về ANSI_NULLS, nhưng không liên quan trực tiếp đến câu hỏi. Tôi không biết về các quy tắc trong đoạn cuối và nó luôn luôn tốt để tìm hiểu thêm. –

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