บริบท DB_ID จากสแต็คการโทรไกลขึ้น


11

ใน SQL Server เป็นไปได้หรือไม่ที่จะรับDB_IDจากบริบทจากระยะไกลกว่า call stack?

เป้าหมายของฉันคือการสร้างฟังก์ชั่นยูทิลิตี้ที่มีประโยชน์ (และแฮ็คยอมรับ) ในฐานข้อมูล dev sandbox ที่ทำให้มันง่ายและรัดกุมเพื่อให้ได้ชื่อของวัตถุที่มีคุณสมบัติครบถ้วนที่กำหนดชื่อแบบสั้นหรือแบบแยกส่วน . ฟังก์ชั่นยูทิลิตี้เหล่านี้จะอยู่ในฐานข้อมูลยูทิลิตี้เดียว แต่เรียกจากฐานข้อมูลอื่น ๆ บนเซิร์ฟเวอร์เดียวกัน

จากสิ่งที่ฉันเห็นจากการทดสอบ:

  • ORIGINAL_DB_NAME()ตามที่ต้องการจะส่งคืนสิ่งที่อยู่ในสตริงการเชื่อมต่อไม่ใช่บริบทปัจจุบัน (กำหนดโดยUSE [dbname])
  • เมื่อเรียกฟังก์ชั่นDB_NAME()ส่งกลับชื่อของฐานข้อมูลที่ฟังก์ชั่นที่กำหนดไว้ อีกวิธีในการพูดแบบนี้คือบริบทภายในฟังก์ชันหรือกระบวนงานที่เก็บไว้คือของฐานข้อมูลที่กำหนดไว้

ฉันรู้ว่าเอ็นจิ้นติดตามสถานะของฐานข้อมูลแต่ละบริบทขึ้น ๆ ลง ๆ สแต็กการโทร (ดูด้านล่างเพื่อพิสูจน์) ดังนั้นมีวิธีการเข้าถึงข้อมูลนี้หรือไม่?

ฉันต้องการที่จะสามารถค้นหาและดำเนินการกับวัตถุในบริบทของฐานข้อมูลของผู้โทรถึงแม้ว่ารหัสการดำเนินการไม่ได้อยู่ในฐานข้อมูลเดียวกัน ตัวอย่างเช่น:

use SomeDB
EXEC util.dbo.frobulate_table 'my_table'

ฉันรู้ว่าฉันสามารถทำได้

EXEC util.dbo.frobulate_table 'SomeDB.dbo.my_table'

แต่ฉันแค่อยากรู้อยากเห็นจริง ๆ ถ้าเป็นไปได้ในการสอบถามสแตกการโทรด้วยวิธีนี้

อัปเดต / บันทึกย่อ

ผมไม่อ่านและดาวน์โหลดรหัสจากบล็อกของกาเบรียล McAdams' นี่เป็นเร็กคอร์ดของ ID โพรซีเดอร์การเรียกขึ้นและลงสแต็ก แต่ยังถือว่าทุกอย่างอยู่ในฐานข้อมูลเดียวกัน

พิสูจน์ SQL Server จำบริบท DB ขึ้นและลง call stack

ตัวอย่าง: บนเซิร์ฟเวอร์ dev ที่มีฐานข้อมูล TestDB1 และ TestDB2

use TestDB1
GO
CREATE FUNCTION dbo.ECHO_DB_NAME() RETURNS nvarchar(128) BEGIN RETURN DB_NAME() END
GO

use TestDB2
GO
CREATE PROCEDURE dbo.ECHO_STACK AS 
BEGIN
    DECLARE @name nvarchar(128)
    SET @name = DB_NAME()
    PRINT 'Before, DB_NAME inside dbo.ECHO_STACK : ' + @name
    SET @name = TestDB1.dbo.ECHO_DB_NAME()        
    PRINT 'TestDB1.dbo.ECHO_DB_NAME returned     : ' + @name
    SET @name = DB_NAME()
    PRINT 'After, DB_NAME inside dbo.ECHO_STACK  : ' + @name
END
GO

use master
SELECT DB_NAME()  -- Returns 'master'
EXEC TestDB2.dbo.ECHO_STACK 

ECHO_STACK proc จัดพิมพ์:

Before, DB_NAME inside dbo.ECHO_STACK : TestDB2
TestDB1.dbo.ECHO_DB_NAME returned     : TestDB1
After, DB_NAME inside dbo.ECHO_STACK  : TestDB2

มันจะเป็นไปได้ผ่านกิจกรรมเสริม แต่เป็นความแปลกใหม่จริงๆ ไม่ใช่สิ่งที่ใช้สำหรับการผลิตอย่างจริงจัง แม้ว่าคุณจะรู้ชื่อฐานข้อมูลคุณจะใช้ยังไง? มีทุกอย่างใน SQL แบบไดนามิกด้วยUSE xyz;ก่อนหน้าหรือไม่
Martin Smith

สุจริตฉันไม่สามารถพูดฉันมีกรณีที่มั่นคงสำหรับเหตุผลนี้จะเป็นสิ่งที่จำเป็น ผมพบว่ามันน่าสนใจมากและถ้าผมทำรูปมันออกมาเราจะใส่มันในสอง procs มีประโยชน์น้อยผมใช้ในฐานข้อมูล Sandbox dev ของฉัน: หนึ่งที่ได้รับชื่อเต็มของวัตถุได้รับส่วนที่รู้จักที่สั้นที่สุดของชื่อ (เช่นใน ตัวอย่างแรกของฉันในคำถาม) และอีกอันหนึ่งที่ฆ่าวัตถุโดยใช้ฟังก์ชันอื่นเพื่อรับชื่อเต็มและใช้ชนิดของวัตถุที่ระบุเพื่อสร้างDROPคำสั่ง
Joshua Honig

@SQLKiwi คำถามมีการปรับปรุงตาม ขอบคุณสำหรับคำตอบอื่น ๆ เช่นกัน ฉันมีฟังก์ชั่น CLR หลากหลายสำหรับการจัดการสตริงดังนั้นนี่จึงเป็นขั้นตอนต่อไปที่เป็นธรรมชาติสำหรับฉัน
Joshua Honig

คำตอบ:


4

คุณไม่สามารถทำสิ่งนี้ได้ด้วยฟังก์ชั่นในฐานข้อมูลยูทิลิตี้ อย่างไรก็ตามคุณสามารถสร้างโพรซีเดอร์ยูทิลีตีในฐานข้อมูลหลักทำเครื่องหมายเป็นอ็อบเจ็กต์ระบบและเรียกใช้จากบริบทของฐานข้อมูลใด ๆ บนระบบของคุณ บทความที่มีตัวอย่างที่ดีสามารถพบได้ในตำแหน่งนี้


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