Làm cách nào để truy vấn nếu một lược đồ cơ sở dữ liệu tồn tại


98

Là một phần của quá trình xây dựng, chúng tôi chạy tập lệnh cập nhật cơ sở dữ liệu khi chúng tôi triển khai mã cho 4 môi trường khác nhau. Hơn nữa, do cùng một truy vấn sẽ được thêm vào cho đến khi chúng tôi thả một thông cáo vào sản xuất nó để có thể chạy nhiều lần trên một cơ sở dữ liệu nhất định. Như thế này:

IF NOT EXISTS (SELECT * FROM sys.tables WHERE object_id = OBJECT_ID(N'[Table]'))
BEGIN
  CREATE TABLE [Table]
  (...)
END

Hiện tại tôi có một câu lệnh tạo lược đồ trong tập lệnh triển khai / xây dựng. Tôi truy vấn sự tồn tại của một lược đồ ở đâu?


2
Vui lòng xem xét việc thay đổi câu trả lời được chấp nhận. Không thể là câu trả lời bạn chấp nhận thực sự có tác dụng với bạn như đã viết.
Aaron Bertrand

Câu trả lời:


165

Bạn đang tìm kiếm sys.schemas ?

IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'jim')
BEGIN
EXEC('CREATE SCHEMA jim')
END

Lưu ý rằng CREATE SCHEMAphải chạy trong lô riêng của nó (theo câu trả lời bên dưới )


Em yêu ... trong thời gian tôi phải chỉnh sửa bài đăng để dễ đọc hơn ... bạn đã khắc phục được sự cố của tôi. Cảm ơn mucho!
Pulsehead 22/10/08

18
đây không phải làm việc trong SQL 2008 vì nhu cầu CREATE SCHEMA là tuyên bố đầu tiên trong đợt một, xem các bài vfilby cho một workaround
sergiom

4
Bạn có thể sử dụng 'Chọn 1 từ sys.schemas' để cải thiện hiệu suất.
vijaysylvester

4
@vijaysylvester Không, đây là chuyện hoang đường. SQL Server tối ưu hóa danh sách cột để bạn đặt gì ở đó không quan trọng. Hoàn toàn bị bỏ qua. Muốn bằng chứng? ĐặtSELECT 1/0...
Aaron Bertrand

1
Tôi đã cập nhật câu trả lời này không thể không đúng (ví dụ sử dụng kịch bản từ bên dưới stackoverflow.com/a/521271/2688 )
bdukes

157

@bdukes là đúng đắn khi xác định xem lược đồ có tồn tại hay không, nhưng câu lệnh trên sẽ không hoạt động trong SQL Server 2005. CREATE SCHEMA <name>cần phải chạy trong lô riêng của nó. Một công việc xung quanh là thực hiện CREATE SCHEMAcâu lệnh trong một tệp thực thi .

Đây là những gì tôi đã sử dụng trong các tập lệnh xây dựng của mình:

IF NOT EXISTS (SELECT 1 FROM sys.schemas WHERE name = '<name>')
BEGIN
    -- The schema must be run in its own batch!
    EXEC( 'CREATE SCHEMA <name>' );
END

hoạt động như một sự quyến rũ! điều này thậm chí cho phép tôi đặt các báo cáo in của tôi và mọi thứ.
Tony

2

Điều này đã cũ nên tôi cảm thấy bắt buộc phải thêm: Đối với SQL SERVER 2008+ Tất cả đều hoạt động (đối với phần được chọn), sau đó sử dụng EXECUTE('CREATE SCHEMA <name>')để thực sự tạo nó trên kết quả âm.

DECLARE @schemaName sysname = 'myfunschema';
-- shortest
If EXISTS (SELECT 1 WHERE SCHEMA_ID(@schemaName) IS NOT NULL)
PRINT 'YEA'
ELSE
PRINT 'NOPE'

SELECT DB_NAME() AS dbname WHERE SCHEMA_ID(@schemaName) IS NOT NULL -- nothing returned if not there

IF NOT EXISTS ( SELECT  top 1 *
                FROM    sys.schemas
                WHERE   name = @schemaName )
PRINT 'WOOPS MISSING'
ELSE
PRINT 'Has Schema'

SELECT SCHEMA_NAME(SCHEMA_ID(@schemaName)) AS SchemaName1 -- null if not there otherwise schema name returned

SELECT SCHEMA_ID(@schemaName) AS SchemaID1-- null if not there otherwise schema id returned


IF EXISTS (
    SELECT sd.SchemaExists 
    FROM (
        SELECT 
            CASE 
                WHEN SCHEMA_ID(@schemaName) IS NULL THEN 0
                WHEN SCHEMA_ID(@schemaName) IS NOT NULL THEN 1
                ELSE 0 
            END AS SchemaExists
    ) AS sd
    WHERE sd.SchemaExists = 1
)
BEGIN
    SELECT 'Got it';
END
ELSE
BEGIN
    SELECT 'Schema Missing';
END

IF schema_id ('MySchemaName') IS NULLhoạt động tốt và có vẻ thuận tiện hơn một chút so với câu trả lời được chấp nhận.
BradC

1

Chỉ để được thêm "phòng thủ", phiên bản sau đây tạo ra một sai lầm loại chuyển đổi vào tài khoản cho khả năng (tuy nhiên không) của> 1 khớp Schema's tương tự như mã xác nhận mức độ thường xuyên cố ý Ném ngoại lệ vì tôi tin rằng nó tốt đến và tôi tin rằng đó là "'phương pháp hay nhất'" để tính đến tất cả các kết quả trả về có thể xảy ra, tuy nhiên khó xảy ra và thậm chí nếu nó chỉ để tạo ra một ngoại lệ nghiêm trọng vì các tác động đã biết của việc dừng xử lý thường tốt hơn các tác động xếp tầng không xác định của các lỗi không bị mắc kẹt. Bởi vì nó rất khó xảy ra, tôi không nghĩ rằng việc Countkiểm tra riêng rẽ + Throwhoặc Try- Catch- Throwđể tạo ra một lỗi nghiêm trọng thân thiện với người dùng hơn nhưng vẫn là lỗi nghiêm trọng.

SS 2005-:

declare @HasSchemaX bit
set @HasSchemaX = case (select count(1) from sys.schemas where lower(name) = lower('SchemaX')) when 1 then 1 when 0 then 0 else 'ERROR' end

SS 2008+:

declare @HasSchemaX bit = case (select count(1) from sys.schemas where lower(name) = lower('SchemaX')) when 1 then 1 when 0 then 0 else 'ERROR' end

Sau đó:

if @HasSchemaX = 1
begin
   ...
end -- if @HasSchemaX = 1

Tôi cho rằng có thể có nhiều giản đồ phù hợp khi bạn sử dụng đối chiếu phân biệt chữ hoa chữ thường, nhưng "xử lý lỗi" của bạn sẽ dẫn đến lỗi sau: Không thể chuyển đổi khi chuyển đổi giá trị varchar 'ERROR' thành kiểu dữ liệu int.
dùng247702

@Stijn: Đó là "By Design" tương tự như cách mã xác thực thường cố ý Throw Exception. Giống như bạn đã nói, nó không "'có khả năng'" xảy ra, vì vậy IMHO, nó không có giá trị toàn bộ Try- Catchhoặc Countkiểm tra riêng để tạo ra một lỗi nghiêm trọng thân thiện với người dùng hơn, nhưng bất kể, tôi có thể sẽ muốn một lỗi nghiêm trọng. Tôi tin vào và tôi tin rằng đó là "'phương pháp hay nhất'" để tính đến tất cả các kết quả trả về có thể xảy ra, tuy nhiên khó xảy ra và ngay cả khi nó chỉ tạo ra một ngoại lệ chết người vì các tác động đã biết của việc ngừng xử lý thường tốt hơn các tác động xếp tầng không xác định của việc không bị mắc kẹt các lỗi.
Tom

Điều đó nghe có vẻ ổn, tôi không chắc đó có phải là cố ý hay không :) Câu trả lời của bạn có thể được hưởng lợi từ một số giải thích bổ sung, giống như bạn vừa đưa ra trong nhận xét của mình.
user247702

@Stijn: peeve vật nuôi của tôi là phổ biến không-để "'thực hành tốt nhất" không kiểm tra nếu một Select, Insert, Updatehoặc DeleteTuyên bố trở lại / bị ảnh hưởng nhiều hơn hoặc ít hơn so với dự kiến # của dòng tuy nhiên khó xảy ra. Ngay cả khi có (đang) Unique Indexhiện tại đảm bảo # (tức là 1) Hàng dự kiến ​​sẽ được trả lại / bị ảnh hưởng, điều đó có thể thay đổi (vô tình hoặc (thiển cận) "" cố ý ") trong tương lai.
Tom

1

Nếu bố cục của các thành phần cho phép, điều này cũng hoạt động.

NẾU TỒN TẠI (CHỌN 1 TỪ sys.schemas WHERE name = 'myschema') ĐẶT NOEXEC BẬT 
đi
TẠO SCHEMA myschema
ĐI 
ĐẶT TẮT NOEXEC - nếu cần xử lý thêm.
ĐI
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.