2016-04-27 15 views
0

所以,在這一點上的小故事:如何將1個包含特定表的數據庫名稱設置爲變量?

我有一個冗長的查詢,我經常使用我的作業,利用sp_MSForEachDB存儲過程。該查詢創建一個臨時表,然後通過並搜索sys.tables,並且如果數據庫有一個名爲T_Study的表,它將運行查詢並將這些結果拖到臨時表中。

我現在試圖做的是從另一個數據庫中加入另一個表,並且此數據庫是不同的類型。這些數據庫全部由存在T_BatchStores區分。所有具有T_BatchStores表的數據庫也將有一個表dbo.T_TSyntax,這是我需要加入的表。基本上,我試圖建立一個通用查詢,我可以在任何包含這個軟件的服務器上運行,並且我有這幾個通用表,但數據庫本身的名稱會有所不同。

所以我想要做的是什麼,我的查詢填充我的臨時表,添加以下內容:我開始和結束中

JOIN '[email protected]+'.dbo.T_TSyntax,然後我的條款等。請記住,這個連接發生子句和那sp_MSforEachDb將在此上運行。

我想@MEDDB只是一個隨機選擇的SQL實例上的任何數據庫的名稱,其中包含一個T_BatchStores表 - 無所謂名稱 - 我只是不想在每次運行時修改查詢它。

如何使用我的DECLARE @MEDDBSET/SELECT @MEDDB來滿足這些要求?

此外,在一些閱讀中,我讀到應該使用SYSNAME作爲數據類型,但我也知道NVARCHAR可以工作 - 但我只想給出一個理想的提示。

我曾嘗試以下:

DECLARE @MEDDB SYSNAME 

SET @MEDDB = (SELECT TOP 1 name FROM sys.databases WHERE EXISTS (SELECT name FROM sys.tables WHERE name = '''T_BATCHSTORES''')) 

SELECT @MEDDB 

但這返回1行與NULL值。我非常喜歡SQL,所以任何幫助將不勝感激!

注意:我目前只使用Microsoft SQL Server 2008和2012。

謝謝!

好的,在大量修改查詢後,這些名稱實際上與我們實際的表結構並不完全相同,下面是我正在使用的查詢的細化版本,以便您能夠看到我要去爲:

/* Add or change variables as needed and comment back in WHERE statements in Insert section as needed. 
You do not need to delete any variables in this section, even if you do not need them. 
Simply comment in or out relevant data in the WHERE clause in Section 4. */ 


/* Section 1: Declaring variables. */ 

DECLARE @STUID NVARCHAR (65) 
DECLARE @IMUID NVARCHAR (200) 
DECLARE @ACCN NVARCHAR (100) 
DECLARE @MEDDB NVARCHAR (255) 

/* Section 2: Assigning values to variables such as an Image file's UID. */ 

SET @STUID = 'enterSTUID' 
SET @IMUID = 'enterIMUIDhere' 
SET @ACCN = 'enterACCNhere' 
SET @MEDDB = (SELECT TOP 1 name FROM sys.databases WHERE [name] LIKE '%med%' 
AND [name] NOT LIKE '%audit%') 


/* Section 3: Creating our temporary table to dump our results. */ 

IF OBJECT_ID('tempdb.dbo.#tempBatchResultsD6') IS NULL 

BEGIN 

CREATE TABLE #tempBatchResultsD6 

(
Database_Name VARCHAR (200), 
THING1 VARCHAR(100) NOT NULL, 
THING2 VARCHAR(200) NOT NULL, 
THING3 DATETIME NOT NULL, 
TSyntaxUID VARCHAR (66) NOT NULL, 
TSyntaxDesc VARCHAR (128) NOT NULL 
) 
END 

TRUNCATE TABLE #tempBatchResultsD6 


/* Section 4: Query that will be used to populate the contents of the temporary table created above. 
Utilizing the stored procedure "sp_MSForEachDb," this will search every database on the SQL instance. 
Here, we are limiting our results to only searching specific databases by only returning results from databases that have a "T_Studies" table. */ 

DECLARE @Command NVARCHAR(MAX) 

SET @Command = N'USE [?]; 
IF EXISTS (SELECT * FROM sys.tables WHERE [name] = ''T_Studies'') 
BEGIN 

INSERT #tempBatchResultsD6 

SELECT 

DB_Name() as Database_Name, 
THING1, 
THING2, 
THING3, 
TS.TSyntaxUID, 
TS.TSyntaxDesc 

FROM T_Studies ST WITH (nolock) 
    JOIN T_Patients PT WITH (nolock) ON ST.ST_PT_FOLDERID = PT.PT_FOLDERID 
    JOIN T_Series SE WITH (nolock) ON ST.ST_FOLDERID = SE.SE_ST_FOLDERID 
    JOIN T_Images IM WITH (nolock) ON SE.SE_FOLDERID = IM.IM_SE_FOLDERID 
    JOIN '[email protected]+'.dbo.T_TSyntaxes TS WITH (nolock) on IM.IM_TSyntaxID = TS.TSyntaxUID 

WHERE ST.STUID = '''[email protected]+''' 
--WHERE IM.IM_UID = '''[email protected]+''' 
--WHERE ST.ST_ACCNNO = '''[email protected]+''' 


END' 

EXEC sp_MSForEachDb @Command 


/* Section 5: Querying our temporary table to get our results. */ 

SELECT 

Database_Name, 
THING1, 
THING2, 
THING3, 
TSyntaxUID, 
TSyntaxDesc 

FROM #tempBatchResultsD6 

ORDER BY Database_Name 

因此,大家可以看到,這是一個巨大的臨時表,將拉離,在他們有一個T_Studies表中的所有數據庫。它的實際形式非常龐大,但是這個比例顯着下降。

問題出現在第2節中,如果名稱包含單詞「Med」而不是「audit」,則使用@MEDDB選擇一個隨機數據庫名稱。這是有問題的,因爲它假定所有網站都有一致的命名 - 雖然建議這些名稱,但它們從來不是保證。

爲了保證一致性,我試圖用包含T_BatchStores表而不是WHERE [name]類似部分的系統上任何數據庫的名稱填充@MEDDB變量。

任何意見這個新的信息將不勝感激!

+0

您不能使用變量作爲源表名稱。但是你可以使用IF-ELSE邏輯或者你可以使用動態SQL ... – Shnugo

+0

你能澄清嗎?我可以使用SELECT @MEDDB =(SELECT name FROM sys.databases WHERE [name] LIKE'%med%' AND [name] NOT LIKE'%audit%')將我的變量設置爲替代,然後加入作品: JOIN'[email protected]+'.dbo.T_TSyntax ... 無法弄清楚爲什麼這是如此不同。 –

回答

0

我不確定我是否完全理解您的問題。 但是,如果你想循環遍歷所有的數據庫,你可以使用類似下面的代碼。然後通過使用「use'+ @DB_Name +';」SELECT XXX「將成爲您的查詢。您切換到所需的數據庫來執行您的查詢。

DECLARE @DB_Name varchar(100) 
DECLARE @Command nvarchar(max) 

DECLARE database_cursor CURSOR FOR 
SELECT name 
FROM MASTER.sys.sysdatabases 

OPEN database_cursor 

FETCH NEXT FROM database_cursor INTO @DB_Name 

WHILE @@FETCH_STATUS = 0 
BEGIN 


    set @Command = 
    ' 
     use ' + @DB_Name + '; 


     SELECT XXX 
    ' 


    EXEC sp_executesql @Command 

    FETCH NEXT FROM database_cursor INTO @DB_Name 

END 

CLOSE database_cursor 
DEALLOCATE database_cursor 
+0

我意識到這個查詢是瘋狂的混淆,直到我可以分享整個事情。由於它是專有軟件,表格名稱是通用的,因此我必須在發佈之前更改所有表格名稱,這樣我纔不會遇到麻煩。和我一起,我會發布完整的東西,以便更清楚我要做什麼。感謝您的迴應! –

+0

好吧,我修改了原始帖子,包含了我要做的修改版本。希望這會有所幫助。 –

0
DECLARE @MEDDB NVARCHAR(500) 
SET @MEDDB = 'SELECT TOP 1 name FROM sys.databases WHERE EXISTS (SELECT name FROM sys.tables WHERE name = ''T_BATCHSTORES'')' 
EXEC (@MEDDB) 

這是動態SQL。當然,我也沒有得到任何結果,但我不在你的數據庫中。不過,這可以讓你成爲「動態」,並使用一個變量來修改的事情:

DECLARE @MEDDB NVARCHAR(500) 
DECLARE @MEDDB2 NVARCHAR(100) = 'T_BATCHSTORES' 
SET @MEDDB = 'SELECT TOP 1 name FROM sys.databases WHERE EXISTS (SELECT name FROM sys.tables WHERE name = ''' + @MEDDB2 + ''')' 
EXEC (@MEDDB) 

我的建議是,你運行簡單的查詢,顯示你想要什麼,然後你將它們置於動態方法。

舉例來說,我在AdventureWorks的現在,所以我可以做:

SELECT * FROM sys.databases 

這給我的一切,都在這裏提供的數據庫的列表。

所以也許我展開來

SELECT * FROM sys.databases WHERE name = 'AdventureWorks' 

這給了我一個行的結果。所以,如果這是我想要的,我把它建立到動態部分:

DECLARE @MEDDB NVARCHAR(500) 
DECLARE @MEDDB2 NVARCHAR(100) = 'AdventureWorks' 
SET @MEDDB = 'SELECT * FROM sys.databases WHERE name =''' + @MEDDB2 + '''' 
EXEC (@MEDDB) 

這一切都取決於你在找什麼。我總是首先找到我想要的數據,然後找出如何使查詢找到它。

+0

好吧,我修改了原來的帖子,以包括我要去的修改版本。希望這會有所幫助。 –

相關問題