วิธีการเปลี่ยนฐานข้อมูลแบบไดนามิกโดยใช้ TSQL


11

ฉันมีปัญหากับการพยายามเปลี่ยนบริบทของ SSMS เป็นฐานข้อมูลที่ระบุใน SQL แบบไดนามิก:

EXEC sys.sp_executesql N'USE db1 ' ;

สามารถดำเนินการได้สำเร็จ แต่บริบทฐานข้อมูลของ SSMS จะไม่เปลี่ยนแปลง

ฉันได้ลองปรับเปลี่ยนเล็กน้อยตามข้างบน

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

ดำเนินการสำเร็จอีกครั้ง แต่ฐานข้อมูลไม่เปลี่ยนแปลง


4
คุณไม่สามารถเปลี่ยนบริบทภายใน sp_executesql สำหรับเซสชันที่คุณใช้ใน SSMS บริบทใช้ได้เฉพาะในระหว่างเซสชัน SQL แบบไดนามิกของคุณเท่านั้นไม่ใช่สำหรับเซสชัน SSMS
Lothar Kraner

คำตอบ:


7

SSMS จะไม่ใช้ซ้ำฉันจะไม่สลับไปยังบริบทของการใช้คำสั่งที่คุณใช้ใน DYNAMIC SQL

หากเป้าหมายสูงสุดคือการเรียกใช้งาน SQL แบบไดนามิกอื่น ๆ ภายในฐานข้อมูลที่เลือกนี่เป็นเรื่องง่ายพอ:

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;

หากคุณต้องการส่งพารามิเตอร์ไม่มีปัญหา:

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;

หากเป้าหมายคือการดำเนินการSQL แบบคงที่ภายในฐานข้อมูลที่เลือกบางทีคุณควรพิจารณาการจัดเก็บ SQL แบบคงที่นั้นในขั้นตอนการจัดเก็บในแต่ละฐานข้อมูลและเรียกมันแบบไดนามิกเช่นนี้:

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;

และหวังว่าเป้าหมายสูงสุดคือการไม่เรียกใช้รหัสนี้ทั้งหมดใน SSMS เพื่อให้ SSMS อยู่ในบริบทของ@db... แดเนียลจะชอบถ้าฉันระบุอย่างชัดเจนว่านี่เป็นไปไม่ได้ตามที่ความคิดเห็นของ @ Lothar ระบุไว้ด้วย


นี่เยี่ยมมากขอบคุณ Aaron Bertrand และไม่เป้าหมายสูงสุดไม่ได้เรียกใช้รหัสนี้ทั้งหมดใน SSMS เพียงเพื่อให้ตอนนี้ SSMS อยู่ในบริบทของ @db
Mazhar

2

DynamicSQL นั้นไม่ได้ดำเนินการตามจริงโดยเฉพาะอย่างยิ่งกับส่วนที่เหลือของรหัสของคุณมันเป็นเอนทิตีที่แยกต่างหาก (แม้ว่ามันจะทำงานราวกับว่ามันอยู่ในสาย

หากคุณเรียกใช้รหัส: SET @sql = N'Use ' + @db + '; select DB_NAME(); select @@spid'ในชุดของชุดปัจจุบันของคุณคุณจะสังเกตเห็นผลลัพธ์ที่กลับมาระบุว่าคุณได้ย้ายฐานข้อมูลที่ใช้งานอยู่ แต่คุณยังคงทำงานภายใต้การเชื่อมต่อเดียวกัน

หากคุณต้องการเปลี่ยนการเลือกฐานข้อมูลในบรรทัดวิธีที่ดีที่สุดคือทำสิ่งนี้:

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

มันไม่ดีหรือสะอาดและต้องการสองบรรทัดต่อฐานข้อมูลที่เป็นไปได้ แต่มันจะทำงานให้เสร็จ (อย่ารันใน SQL แบบไดนามิกหรือคุณจะจบลงด้วยปัญหาเดียวกันของเธรดหลักที่ไม่มีการเปลี่ยนแปลง)

โปรดทราบว่าห้ามใช้คำสั่ง USE ในขั้นตอน / ฟังก์ชั่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.