क्या एक चर को जारी रखने का एक तरीका है?


82

क्या एक चर को जारी रखने का एक तरीका है?

Declare @bob as varchar(50);
Set @bob = 'SweetDB'; 
GO
USE @bob  --- see note below
GO
INSERT INTO @bob.[dbo].[ProjectVersion] ([DB_Name], [Script]) VALUES (@bob,'1.2')

'USE @bob' लाइन के लिए यह SO प्रश्न देखें ।


आपको डीबी नाम के साथ तालिका नाम को अर्हता प्राप्त करने की आवश्यकता क्यों है? मुझे लगता है कि इस से पहले एक समान प्रश्न पूछा गया था।
शाहकलेश

और इस तरह एक चर में डेटाबेस नाम के साथ तालिका के नाम को अर्हता प्राप्त करने का कोई तरीका नहीं है। यूएसई स्टेटमेंट के साथ एक चर का उपयोग करने के बारे में उनके पिछले प्रश्न के साथ, मैं अनुमान लगा रहा हूं कि वह गतिशील एसक्यूएल में सब कुछ करने की जरूरत है, जो सभी दर्द के साथ टेबल पर जाता है।
लास वी। कार्लसन

वास्तविक स्क्रिप्ट 4 विभिन्न डेटाबेस को एकीकृत करता है। मैंने dbName1, dbName2, dbName3 और dbName4 को खोजने और बदलने के निर्देश दिए हैं। मुझे लगा कि क्लाइंट के लिए सिर्फ चार वेरिएबल सेट करने में त्रुटि कम होगी।
NitroxDM

प्रश्न शीर्षक वास्तव में एक महत्वपूर्ण प्रश्न है, लेकिन उदाहरण कोड भयानक है। जैसा कि स्वीकृत उत्तर दिखाता है, आपको अपने उदाहरण में 'गो' की आवश्यकता नहीं थी। परिणाम यह है कि स्वीकृत उत्तर आपके शीर्षक में प्रश्न का उत्तर नहीं देता है।
ग्रेग वुड्स

जवाबों:


31

goआदेश अलग बैचों में कोड विभाजित करने के लिए प्रयोग किया जाता है। यदि वास्तव में आप क्या करना चाहते हैं, तो आपको इसका उपयोग करना चाहिए, लेकिन इसका मतलब है कि बैच वास्तव में अलग हैं, और आप उनके बीच चर साझा नहीं कर सकते।

आपके मामले में समाधान सरल है; आप केवल goबयान निकाल सकते हैं, उन्हें उस कोड की आवश्यकता नहीं है।

साइड नोट: आप किसी useस्टेटमेंट में वैरिएबल का उपयोग नहीं कर सकते हैं , इसे डेटाबेस का नाम होना चाहिए।


1
कुछ SQL कथन एक ब्लॉक (GO स्टेटमेंट्स के बीच का क्षेत्र) में पहला स्टेटमेंट होना चाहिए। उदाहरण के लिए: क्रिएट प्रक्रिया या क्रिएट फंक्शन दोनों किसी भी अन्य बयान से पहले होने चाहिए - या तो स्क्रिप्ट के शीर्ष पर या GO स्टेटमेंट के तुरंत बाद (ध्यान दें: इन बयानों से पहले सफेद स्थान और टिप्पणियों की अनुमति है)। जब स्क्रिप्ट्स चल रही हों, जहां अन्य लॉजिक के बाद ऐसे स्टेटमेंट्स होने चाहिए, GO स्टेटमेंट्स की आवश्यकता होती है। लेकिन मुझे इस बात से सहमत होना चाहिए कि ज्यादातर मामलों में, GO स्टेटमेंट को हटाया जा सकता है।
ज़ेरेफेथ

@Zarepheth: अच्छी बात है। इस विशिष्ट कोड में इसकी आवश्यकता नहीं है, लेकिन यह जानना उपयोगी है कि कुछ मामलों में इनकी आवश्यकता हो सकती है।
गुफ़ा

1
क्यों होता है पतन? यदि आप यह नहीं समझाते हैं कि ऐसा क्या है जो आपको लगता है कि यह गलत है, तो इससे उत्तर में सुधार नहीं हो सकता है।
गुफ़ा

2
@jwize: नहीं, आपको उन्हें अलग करने की आवश्यकता नहीं है, जो एक ही ब्लॉक में किया जा सकता है।
गुफ़ा

1
@Ben: goकमांड का उपयोग कोड को अलग-अलग बैचों में विभाजित करने के लिए किया जाता है। यदि आप ऐसा करना चाहते हैं, तो आपको इसका उपयोग करना चाहिए, लेकिन इसका मतलब है कि बैच वास्तव में अलग हैं, और आप उनके बीच चर साझा नहीं कर सकते।
गुफ़ा

127

एक अस्थायी तालिका का उपयोग करें:

CREATE TABLE #variables
    (
    VarName VARCHAR(20) PRIMARY KEY,
    Value VARCHAR(255)
    )
GO

Insert into #variables Select 'Bob', 'SweetDB'
GO

Select Value From #variables Where VarName = 'Bob'
GO

DROP TABLE #variables
go

13
शानदार जवाब ... आपने वास्तव में आस-पास काम देने के बजाय सवाल पूछ लिया।
कॉस कैलिस

1
यह सही जवाब है। अच्छा समाधान है। यह अतिरिक्त रूप से अच्छा है कि, यदि आप बड़ी संख्या में चर का उपयोग करते हैं, तो वे सभी आसानी से सुलभ तालिका में हैं, कोई भी स्क्रॉलिंग नहीं करता है और एसपी आपकी घोषणाओं की तलाश में है।
कॉलिनमैक

15

मैं इस प्रश्न के इस उत्तर को ग्लोबल वेरिएबल्स विद गो के साथ पसंद करता हूं

जो जोड़ा है वह करने में सक्षम होने का लाभ है जो आप मूल रूप से भी करना चाहते थे।

चेतावनी यह है कि आपको SQLCMD मोड (Query-> SQLCMD के तहत) चालू करना होगा या इसे सभी क्वेरी विंडो के लिए डिफ़ॉल्ट रूप से चालू करना होगा (उपकरण-> विकल्प फिर क्वेरी परिणाम-> डिफ़ॉल्ट रूप से, SQLCMD मोड में नए प्रश्न खोलें)

फिर आप निम्न प्रकार के कोड का उपयोग कर सकते हैं (पूरी तरह से ऑस्कर ई। फ्रैक्सेडस टॉमो द्वारा उसी उत्तर से काट दिया गया )

--Declare the variable
:setvar MYDATABASE master
--Use the variable
USE $(MYDATABASE);
SELECT * FROM [dbo].[refresh_indexes]
GO
--Use again after a GO
SELECT * from $(MYDATABASE).[dbo].[refresh_indexes];
GO

मैं SQLCMD मोड में क्वेरी फ़ाइल को किसी अन्य फ़ाइल (: फ़ाइल नाम से बाहर) पर पुनर्निर्देशित कर रहा था, और आउटपुट को उस फ़ाइल पर वापस लाने के लिए, जिसे आपको किसी GO को निष्पादित करना है, इसलिए यह: सेवर सिंटैक्स उस स्थिति में सामान्य चर को बदलने के लिए आवश्यक है जब से आप ' फिर से चीजों को बैचों में विभाजित करने के लिए मजबूर किया गया।
Anssssss

महान! यह वास्तव में वास्तविक सही उत्तर के रूप में चिह्नित किया जाना चाहिए!
SQL पुलिस

3

यदि आप SQL सर्वर का उपयोग कर रहे हैं, तो आप संपूर्ण स्क्रिप्ट के लिए वैश्विक चर सेट कर सकते हैं जैसे:

:setvar sourceDB "lalalallalal"

और स्क्रिप्ट में बाद में उपयोग करें:

$(sourceDB)

सुनिश्चित करें कि SQL प्रबंध मोड मोड सर्वर प्रबंधन स्टडी में है, आप शीर्ष मेनू पर क्लिक करें क्वेरी के माध्यम से और SQLCMD मोड को चालू कर सकते हैं।

विषय पर और अधिक जानकारी यहाँ मिल सकती है: एमएस डॉक्यूमेंटेशन


1

यकीन नहीं होता, अगर यह मदद करता है

declare @s varchar(50)
set @s='Northwind'

declare @t nvarchar(100)
set @t = 'select * from ' + @s + '.[dbo].[Customers]'

execute sp_executesql @t

1

अस्थायी विवरणों को GO स्टेटमेंट्स पर बनाए रखा जाता है, इसलिए ...

SELECT 'value1' as variable1, 'mydatabasename' as DbName INTO #TMP

-- get a variable from the temp table
DECLARE @dbName VARCHAR(10) = (select top 1 #TMP.DbName from #TMP)
EXEC ('USE ' + @dbName)
GO

-- get another variable from the temp table
DECLARE @value1 VARCHAR(10) = (select top 1 #TMP.variable1 from #TMP)

DROP TABLE #TMP

यह सुंदर नहीं है, लेकिन यह काम करता है


1

अपनी स्वयं की संग्रहीत कार्यविधियाँ बनाएँ जो एक अस्थायी तालिका में / लोड को बचाती हैं।

MyVariableSave   -- Saves variable to temporary table. 
MyVariableLoad   -- Loads variable from temporary table.

तब आप इसका उपयोग कर सकते हैं:

print('Test stored procedures for load/save of variables across GO statements:')

declare @MyVariable int = 42
exec dbo.MyVariableSave @Name = 'test', @Value=@MyVariable
print('  - Set @MyVariable = ' + CAST(@MyVariable AS VARCHAR(100)))

print('  - GO statement resets all variables')
GO -- This resets all variables including @MyVariable

declare @MyVariable int
exec dbo.MyVariableLoad 'test', @MyVariable output
print('  - Get @MyVariable = ' + CAST(@MyVariable AS VARCHAR(100)))

आउटपुट:

Test stored procedures for load/save of variables across GO statements:
  - Set @MyVariable = 42
  - GO statement resets all variables
  - Get @MyVariable = 42

आप इनका उपयोग भी कर सकते हैं:

exec dbo.MyVariableList       -- Lists all variables in the temporary table.
exec dbo.MyVariableDeleteAll  -- Deletes all variables in the temporary table.

का आउटपुट exec dbo.MyVariableList:

Name    Value
test    42

यह पता चलता है कि तालिका में सभी चर को सूचीबद्ध करने में सक्षम होना वास्तव में काफी उपयोगी है। इसलिए भले ही आप बाद में एक चर को लोड न करें, लेकिन डिबगिंग के उद्देश्यों के लिए यह बहुत अच्छा है कि एक ही जगह पर सब कुछ देखें।

यह एक ##उपसर्ग के साथ एक अस्थायी तालिका का उपयोग करता है , इसलिए यह केवल GO कथन से बचने के लिए पर्याप्त है। इसका उपयोग किसी एक लिपि के भीतर किया जाना है।

और संग्रहीत कार्यविधियाँ:

-- Stored procedure to save a variable to a temp table.
CREATE OR ALTER PROCEDURE MyVariableSave 
    @Name varchar(255),
    @Value varchar(MAX)
WITH EXECUTE AS CALLER
AS  
BEGIN
    SET NOCOUNT ON
    IF NOT EXISTS (select TOP 1 * from tempdb.sys.objects where name = '##VariableLoadSave')
    BEGIN
        DROP TABLE IF EXISTS ##VariableLoadSave
        CREATE TABLE ##VariableLoadSave
        (
            Name varchar(255),
            Value varchar(MAX)
        )
    END
    UPDATE ##VariableLoadSave SET Value=@Value WHERE Name=@Name
    IF @@ROWCOUNT = 0
        INSERT INTO ##VariableLoadSave SELECT @Name, @Value
END
GO
-- Stored procedure to load a variable from a temp table.
CREATE OR ALTER PROCEDURE MyVariableLoad 
    @Name varchar(255),
    @Value varchar(MAX) OUT
WITH EXECUTE AS CALLER
AS  
BEGIN
    IF EXISTS (select TOP 1 * from tempdb.sys.objects where name = '##VariableLoadSave')
    BEGIN
        IF NOT EXISTS(SELECT TOP 1 * FROM ##VariableLoadSave WHERE Name=@Name)
        BEGIN
            declare @ErrorMessage1 as varchar(200) = 'Error: cannot find saved variable to load: ' + @Name
            raiserror(@ErrorMessage1, 20, -1) with log
        END

        SELECT @Value=CAST(Value AS varchar(MAX)) FROM ##VariableLoadSave
        WHERE Name=@Name
    END
    ELSE
    BEGIN
        declare @ErrorMessage2 as varchar(200) = 'Error: cannot find saved variable to load: ' + @Name
        raiserror(@ErrorMessage2, 20, -1) with log
    END
END
GO
-- Stored procedure to list all saved variables.
CREATE OR ALTER PROCEDURE MyVariableList
WITH EXECUTE AS CALLER
AS  
BEGIN
    IF EXISTS (select TOP 1 * from tempdb.sys.objects where name = '##VariableLoadSave')
    BEGIN
        SELECT * FROM ##VariableLoadSave
        ORDER BY Name
    END
END
GO
-- Stored procedure to delete all saved variables.
CREATE OR ALTER PROCEDURE MyVariableDeleteAll
WITH EXECUTE AS CALLER
AS  
BEGIN
    DROP TABLE IF EXISTS ##VariableLoadSave
    CREATE TABLE ##VariableLoadSave
    (
        Name varchar(255),
        Value varchar(MAX)
    )
END

0

यदि आपको बस एक बाइनरी हाँ / नहीं (जैसे कि कोई कॉलम मौजूद है) की आवश्यकता है, तो आप SET NOEXEC ONस्टेटमेंट्स के निष्पादन को अक्षम करने के लिए उपयोग कर सकते हैं । SET NOEXEC ONजीओ (बैचों के पार) में काम करता है। लेकिन पर EXEC फिर से चालू करना याद के साथ SET NOEXEC OFFस्क्रिप्ट के अंत में।

IF COL_LENGTH('StuffTable', 'EnableGA') IS NOT NULL
    SET NOEXEC ON -- script will not do anything when column already exists

ALTER TABLE dbo.StuffTable ADD EnableGA BIT NOT NULL CONSTRAINT DF_StuffTable_EnableGA DEFAULT(0)
ALTER TABLE dbo.StuffTable SET (LOCK_ESCALATION = TABLE)
GO
UPDATE dbo.StuffTable SET EnableGA = 1 WHERE StuffUrl IS NOT NULL
GO
SET NOEXEC OFF

यह बयानों को संकलित करता है लेकिन उन्हें निष्पादित नहीं करता है। यदि आप स्कीमा का संदर्भ नहीं देते हैं तो भी आपको "संकलन त्रुटियां" मिलेंगी। तो यह स्क्रिप्ट 2 रन (जो मैं कर रहा हूं) को "बंद" करने के लिए काम करता है, लेकिन 1 रन पर स्क्रिप्ट के कुछ हिस्सों को बंद करने के लिए काम नहीं करता है, क्योंकि कॉलम या तालिकाओं को संदर्भित करने पर आपको अभी भी संकलन त्रुटियां मिलेंगी 'अभी तक मौजूद नहीं है।


0

आप NOEXEC का उपयोग कर सकते हैं नीचे दिए गए चरणों का पालन करें:

तालिका बनाएं

#temp_procedure_version(procedure_version varchar(5),pointer varchar(20))

एक अस्थायी तालिका में संस्करण के लिए प्रक्रिया संस्करण और सूचक डालें #temp_procedure_version

--example process_version पॉइंटर

temp_procedure_versionमानों में डालें (1.0, 'पहला संस्करण')

temp_procedure_versionमूल्यों में डालें (2.0, 'अंतिम संस्करण')

फिर प्रक्रिया संस्करण को पुनः प्राप्त करें, आप निम्न कथन के अनुसार स्थिति का उपयोग कर सकते हैं

जहाँ @ProcedureVersion=ProcedureVersionसे चयन करें#temp_procedure_versionpointer='first version'

IF (@ProcedureVersion='1.0')
    BEGIN
    SET NOEXEC OFF  --code execution on 
    END
ELSE
    BEGIN 
    SET NOEXEC ON  --code execution off
    END 

- इन्टरसेर प्रक्रिया संस्करण 1.0 यहाँ

प्रक्रिया संस्करण 1.0 बनाएं .....

SET NOEXEC OFF -- execution is ON

चयन @ProcedureVersion=ProcedureVersionसे #temp_procedure_versionजहां सूचक = 'अंतिम संस्करण'

IF (@ProcedureVersion='2.0')
    BEGIN
    SET NOEXEC OFF  --code execution on 
    END
ELSE
    BEGIN 
    SET NOEXEC ON  --code execution off
    END 

प्रक्रिया संस्करण 2.0 बनाएं .....

SET NOEXEC OFF -- execution is ON

अस्थायी तालिका देखें

ड्रॉप तालिका #temp_procedure_version

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.