2009-04-06 29 views
7

tôi có một tình huống mà tôi muốn kiểm tra một cột nào đó (như số phiên bản) và sau đó áp dụng một loạt các DDL thay đổichạy câu lệnh DDL có điều kiện trên máy chủ sql

rắc rối là tôi không thể làm điều đó với trong một khối IF BEGIN END, vì các câu lệnh DDL yêu cầu bộ tách GO giữa chúng và TSQL sẽ không cho phép điều đó.

Tôi tự hỏi nếu có bất kỳ cách nào xung quanh để thực hiện điều này

Trả lời

0

GO được công nhận bởi các công cụ của khách hàng chứ không phải bởi máy chủ. Bạn có thể có CREATE trong các thủ tục được lưu trữ hoặc truy vấn đặc biệt của bạn mà không có GO.

1

Nhiều câu lệnh "IF"? Sau đó, bạn có thể kiểm tra sự thành công của các câu lệnh DDL tiếp theo

SQL động? EXEC ('ALTER TABLE foo WITH CHECK ADD CONSTRAINT ...')?

Như đã đề cập, GO là một máy tách lô hàng duy nhất của khách hàng để chia nhỏ một khối văn bản SQL thành các lô được gửi tới Máy chủ SQL.

+0

sql động sẽ trở nên lộn xộn rất sớm, vì tôi có sql động bên trong các thủ tục tự –

+0

OK, nhiều câu lệnh IF ... – gbn

6

Bạn không cần sử dụng toàn bộ khối. Một điều kiện sẽ thực thi câu lệnh tiếp theo trong toàn bộ nếu bạn không sử dụng BEGIN/END - bao gồm một câu lệnh DDL duy nhất. Điều này tương đương với hành vi của nếu trong Pascal, C, v.v. Tất nhiên, điều đó có nghĩa là bạn sẽ phải kiểm tra lại tình trạng của bạn nhiều lần. Nó cũng có nghĩa là sử dụng các biến để kiểm soát hành vi của tập lệnh là khá nhiều trong số các câu hỏi.

[Edit: CREATE PROCEDURE không hoạt động trong ví dụ dưới đây, vì vậy tôi đã thay đổi nó để cái gì khác và chuyển CREATE PROCEDURE cho một cuộc thảo luận kéo dài hơn dưới đây]

If ((SELECT Version FROM table WHERE...) <= 15) 
CREATE TABLE dbo.MNP (
.... 
) 
GO 

If ((SELECT Version FROM table WHERE...) <= 15) 
ALTER TABLE dbo.T1 
ALTER COLUMN Field1 AS CHAR(15) 
GO 

... 

Hoặc một cái gì đó như thế, tùy thuộc vào tình trạng của bạn.

Thật không may, CREATE/ALTER PROCEDURE và CREATE/ALTER VIEW có các yêu cầu đặc biệt khiến việc làm việc trở nên khó khăn hơn nhiều. Chúng được yêu cầu khá nhiều là điều duy nhất trong một tuyên bố, vì vậy bạn không thể kết hợp chúng với IF chút nào.

Đối với nhiều kịch bản, khi bạn muốn "nâng cấp" đối tượng của bạn, bạn có thể làm việc nó như là một thả có điều kiện tiếp theo là một tạo:

IF(EXISTS(SELECT * FROM sys.objects WHERE type='p' AND object_id = OBJECT_ID('dbo.abc'))) 
DROP PROCEDURE dbo.abc 
GO 

CREATE PROCEDURE dbo.abc 
AS 
    ... 
GO 

Nếu bạn thực sự cần logic có điều kiện để quyết định những việc cần làm , thì cách duy nhất tôi biết là sử dụng EXECUTE để chạy các câu lệnh DDL dưới dạng một chuỗi.

If ((SELECT Version FROM table WHERE...) <= 15) 
EXECUTE 'CREATE PROC dbo.abc 
AS 
    .... 
') 

Nhưng điều này rất đau đớn. Bạn phải thoát khỏi bất kỳ dấu ngoặc kép nào trong phần nội dung của quy trình và thật khó đọc.

Tùy thuộc vào những thay đổi bạn cần áp dụng, bạn có thể thấy tất cả những điều này có thể rất nhanh. Ở trên thậm chí không bao gồm kiểm tra lỗi, đó là một nỗi đau hoàng gia tất cả ngày của riêng mình. Đây là lý do tại sao đám thợ làm kiếm kiếm sống bằng cách tìm ra cách để tự động hóa việc tạo tập lệnh triển khai.

Rất tiếc; không có cách nào "dễ dàng" phù hợp với mọi thứ. Đây chỉ là thứ mà TSQL hỗ trợ rất kém. Tuy nhiên, ở trên nên là một khởi đầu tốt.

+0

Nếu ((SELECT Version FROM table WHERE ...) <= 15) TẠO THỦ TỤC TẠO dbo.abc AS cú pháp này sẽ không hoạt động .... nó nói cú pháp sai gần từ khóa 'PROCEDURE' –

+1

Bạn là chính xác! Lấy làm tiếc. Xem? Tôi đã nói với bạn nó là lộn xộn (dạy tôi để trả lời một câu hỏi lúc 2 giờ sáng). T-SQL yêu cầu CREATE PROC là câu lệnh ONLY trong một "batch" (giữa GO). Tôi đã cố định mẫu ở trên và cung cấp cho bạn thêm chi tiết về vấn đề này. Chúc may mắn. –

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