Cách thay đổi cơ sở dữ liệu bằng TSQL


11

Tôi gặp sự cố khi cố gắng thay đổi động bối cảnh SSMS thành cơ sở dữ liệu được chỉ định trong SQL động:

EXEC sys.sp_executesql N'USE db1 ' ;

Nó thực thi thành công tuy nhiên bối cảnh cơ sở dữ liệu của SSMS không thay đổi.

Tôi đã thử một sửa đổi nhỏ cho như trên

DECLARE @sql NVARCHAR(100) DECLARE @db NVARCHAR(50)
SET @db = N'db1' SET @sql = N'Use ' + @db
EXEC sp_executesql @sql

Một lần nữa, nó thực thi thành công, nhưng cơ sở dữ liệu không thay đổi.


4
Bạn không thể thay đổi bối cảnh trong sp_executesql cho phiên bạn đang sử dụng trong SSMS. Ngữ cảnh chỉ hợp lệ trong phiên SQL động của bạn - không dành cho phiên SSMS.
Lothar Kraner

Câu trả lời:


7

SSMS S NOT KHÔNG, TÔI SỬA CHỮA, S SW KHÔNG CHUYỂN ĐẾN TIẾP THEO MỘT QUY TẮC SỬ DỤNG BẠN CHẠY TRONG SQL NĂNG ĐỘNG.

Nếu mục tiêu cuối cùng là thực thi một số SQL động khác bên trong cơ sở dữ liệu đã chọn, thì điều này đủ dễ dàng:

DECLARE @db sysname = N'db1';

DECLARE @exec nvarchar(max) = QUOTENAME(@db) + N'.sys.sp_executesql',
        @sql  nvarchar(max) = N'SELECT DB_NAME();';

EXEC @exec @sql;

Nếu bạn cần truyền tham số, không có vấn đề gì:

DECLARE @db sysname = N'db1', @i int = 1;

DECLARE @exec nvarchar(max) = QUOTENAME(@db) + N'.sys.sp_executesql',
        @sql  nvarchar(max) = N'SELECT DB_NAME(), @i;';

EXEC @exec @sql, N'@i int', @i;

Nếu mục tiêu là thực thi một số SQL tĩnh bên trong cơ sở dữ liệu đã chọn, có lẽ bạn nên xem xét việc lưu trữ SQL tĩnh đó trong một thủ tục được lưu trữ trong mỗi cơ sở dữ liệu và gọi nó một cách linh hoạt như sau:

DECLARE @db sysname = N'db1';

DECLARE @exec nvarchar(max) = QUOTENAME(@db) + N'.sys.sp_executesql',
        @sql  nvarchar(max) = N'EXEC dbo.procedurename;';

EXEC @exec @sql;

Và hy vọng mục tiêu cuối cùng là không chạy tất cả mã này trong SSMS để SSMS hiện đang ở trong bối cảnh @db... Daniel thực sự thích nó nếu tôi tuyên bố rõ ràng rằng điều này là không thể, như nhận xét của @ Lothar cũng nêu.


Điều này thật tuyệt, cảm ơn Aaron Bertrand. Và không, mục tiêu cuối cùng không phải là chạy tất cả mã này trong SSMS chỉ để SSMS hiện đang ở trong bối cảnh của @db
Mazhar

2

DynamicQuery không thực sự được thực thi cụ thể phù hợp với phần còn lại của mã của bạn, nó là một thực thể riêng biệt (mặc dù nó được chạy như thể nó là nội tuyến

Nếu bạn chạy mã: SET @sql = N'Use ' + @db + '; select DB_NAME(); select @@spid'ngay lập tức trong tập hợp hiện tại của bạn, bạn sẽ nhận thấy kết quả quay lại cho biết bạn đã di chuyển cơ sở dữ liệu đang hoạt động, nhưng bạn vẫn đang chạy trong cùng một kết nối.

Nếu bạn muốn thay đổi lựa chọn cơ sở dữ liệu nội tuyến, cách tốt nhất là làm một cái gì đó như thế này:

IF @db = 'db1'
    USE db1
ELSE IF @db = 'db2'
    USE db2

Nó không đẹp hoặc sạch và yêu cầu hai dòng trên mỗi cơ sở dữ liệu tiềm năng nhưng nó sẽ hoàn thành công việc (không chạy nó trong SQL động hoặc bạn vẫn sẽ gặp phải vấn đề tương tự của luồng chính không bị thay đổi)

Lưu ý rằng việc sử dụng các lệnh USE bị cấm trong các thủ tục / chức năng

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.