টিএসকিউএল - কোনও BEGIN .. শেষ ব্লকের অভ্যন্তরে কীভাবে ব্যবহার করবেন?


97

আমি একাধিক বিকাশ ডাটাবেস থেকে স্টেজিং / উত্পাদনে স্বয়ংক্রিয়ভাবে পরিবর্তনগুলি স্থানান্তরিত করার জন্য একটি স্ক্রিপ্ট তৈরি করছি। মূলত, এটি পরিবর্তন-স্ক্রিপ্টগুলির একগুচ্ছ লাগে এবং এগুলি প্রতিটি স্ক্রিপ্টকে IF whatever BEGIN ... ENDবিবৃতিতে মোড়ানো একটি একক স্ক্রিপ্টে মিশে যায় ।

যাইহোক, কিছু স্ক্রিপ্টগুলির একটি GOবিবৃতি প্রয়োজন যাতে উদাহরণস্বরূপ, এসকিউএল বিশ্লেষক এটি তৈরি করার পরে একটি নতুন কলাম সম্পর্কে জানে।

ALTER TABLE dbo.EMPLOYEE 
ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO -- Necessary, or next line will generate "Unknown column:  EMP_IS_ADMIN"
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever

যাইহোক, একবার আমি এটি একটি IFব্লকে মোড়ানো :

IF whatever
BEGIN
    ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
    GO
    UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
END

এটি ব্যর্থ হয়েছে কারণ আমি BEGINকোনও মিল নেই প্রেরণ করছি END। তবে, আমি যদি GOএটি মুছে ফেলি তবে এটি অজানা কলাম সম্পর্কে আবার অভিযোগ করে।

একক IFব্লকের মধ্যে একই কলামটি তৈরি এবং আপডেট করার কোনও উপায় আছে কি ?


4
দেখুন stackoverflow.com/questions/4855537/... দয়া
gbn

4
@ জিবিএন: হ্যাঁ, আমি বুঝতে পারি কেন এটি ঘটে (দ্বিতীয় অনুচ্ছেদ দেখুন) ; তবে কীভাবে এটিকে ঘিরে কাজ করা যায় তা সম্পর্কে আমার কোনও ধারণা নেই - আমার কি প্রতিটি জিজ্ঞাসাকে স্ট্রিংয়ের গুচ্ছ হিসাবে রূপান্তরিত করা দরকার !?
ব্লুরাজা - ড্যানি প্লেফুঘুফুট

@ ব্লুরাজা: উদ্বেগ কী? যদি এটি কাজ করে তবে দিনের শেষে যা কিছু ঘটে তা গুরুত্বপূর্ণ। প্রদত্ত সমাধানটিতে যদি কোনও বৈধ ব্যবসায়ের সমস্যা থাকে তবে দয়া করে তা প্রকাশ করুন। প্রতিটি ক্যোয়ারিকে স্ট্রিংয়ের গোছায় রূপান্তর করার বিষয়ে কি বিশেষভাবে কিছুটা উদ্বেগ রয়েছে?
মেল্লামব্যাক

4
@ মেল্লামোকব: হ্যাঁ, সমস্যা আছে; যদি GO শব্দটি অন্য কোনও প্রসঙ্গে ব্যবহৃত হয় (যেমন একটি মন্তব্য বা স্ট্রিং), স্ক্রিপ্টটি কাজ করবে না। এছাড়াও, কিছু ভুল হয়ে গেলে আমরা ত্রুটি বার্তাগুলিতে দরকারী লাইন নম্বরগুলি হারাব। লেনদেনের সাথে এটি করার কোনও উপায় নেই? নাকি চেষ্টা / ধর?
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

@ ব্লুরাজা: ১) আমি বিশ্বাস করি GOনিজেই এক লাইনে থাকতে হবে, সুতরাং আপনি কেবল সেই ক্ষেত্রেই অনুসন্ধান করতে পারেন, শব্দের প্রতিটি উদাহরণই নয় GO। 2) আপনি সর্বদা লগ করতে পারেন যা বিবৃতি সফলভাবে সম্পন্ন হয়েছে। অথবা আপনি চেষ্টা করে পুরো জিনিসটি মুছে ফেলতে / ধরতে এবং নিজের লাইনের নম্বরগুলি কিছু ভেরিয়েবল, যেমন @ লাইননো ব্যবহার করে ব্যবহার করতে পারেন, যাতে আপনি ট্র্যাক রাখেন এবং ত্রুটি সম্পর্কে রিপোর্ট করেছিলেন। আপনি যেহেতু এগুলি স্বয়ংক্রিয়ভাবে উত্পন্ন করছেন তাই এর পরিবর্তিত পরিবর্তনগুলি একটি হাওয়া হওয়া উচিত। আপনার মতামতটি কেবল মনে হচ্ছে যখন আপনার সমস্ত উদ্বেগের সমাধানের সমাধান রয়েছে বলে আমি মনে করি আপনি এই রুটটি অন্বেষণ করতে চান না।
মেল্লামোকব

উত্তর:


47

আমার একই সমস্যা ছিল এবং অবশেষে সেট নক্সেক্স ব্যবহার করে এটি সমাধান করতে সক্ষম হয়েছি

IF not whatever
BEGIN
    SET NOEXEC ON; 
END

ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever

SET NOEXEC OFF; 

4
এটি একটি দুর্দান্ত সমাধান!
বাজিঙ্গা

+1! এটি কোনও এসএস মোড স্ক্রিপ্টে (যেমন একটি মাস্টার ডিপ্লোয়মেন্ট স্ক্রিপ্ট) ব্যবহারের জন্য এখন পর্যন্ত কেবলমাত্র একমাত্র বাস্তব উত্তর SQLCMDযা বিবৃতিতে :rএই কলগুলির সাথে কিছু অন্যান্য এসএস স্ক্রিপ্টগুলি (যেমন উপ-স্থাপনার স্ক্রিপ্ট) কল করে ( কমান্ডের মাধ্যমে ) if। ওডেস, মেল্লামব্যাক এবং অ্যান্ডি জোয়ারারের কলগুলি / - এর সমস্ত বিবৃতি বন্ধ করে দেওয়ার উত্তরগুলি অ-স্টার্টার নয়। এছাড়াও, বিবৃতি (উদাহরণস্বরূপ এর আগে একটি স্পষ্টের প্রয়োজন হয় ) থাকলে - পদ্ধতিটি কাজ করবে না । কিন্তু, মানুষ, "হলি ডাবল নেগেটিভ, ব্যাটম্যান!" ;)execbeginendbeginendcreatego
টম

পঠনযোগ্যতার জন্য (উদাহরণস্বরূপ, ডাবল-নেগেটিভগুলি কাটিয়ে উঠতে এবং এটি আরও ভার্চুয়াল- if ব্লককে অনুকরণকারী করে তুলতে সাহায্য করার জন্য ), আমি একটি -- If whateverমন্তব্য দিয়ে ব্লকটির উপসর্গ করব, ব্লকটি ইন্ডেন্ট করব এবং একটি --end If whateverমন্তব্যে ব্লকটি পোস্টফিক্স করব ।
টম

তুমি আমার বেকন বাঁচিয়েছ! আমি একত্রীকরণের বিবৃতি চালিয়ে যাচ্ছিলাম এবং সেই বোবা
গোয়াদের কোনও আইফিনের

এইচএম, সেট নেক্সেক চালু হওয়ার পরে আমি কোনওভাবে আপডেটে ত্রুটি পাচ্ছি? (আপডেট করার জন্য কলামের নামটি অবৈধ error ত্রুটি) ক্যোয়ারী সম্পাদকটিতে এমএসএসকিউএল 2014 এ চলছে। শর্তটি মিথ্যা হয়ে থাকলে ঠিকঠাক কাজ করে (এভাবে noexec বন্ধ থাকে)
জেরি

44

GO এসকিউএল নয় - এটি কেবলমাত্র এমএস এসকিউএল সরঞ্জামগুলিতে ব্যাচের বিভাজক।

যদি আপনি এটি ব্যবহার না করেন তবে আপনার অবশ্যই বিবৃতিগুলি পৃথকভাবে সম্পাদন করা দরকার - হয় বিভিন্ন ব্যাচে বা জনসংখ্যার জন্য গতিশীল এসকিউএল ব্যবহার করে (ধন্যবাদ @ জিবিএন):

IF whatever
BEGIN
    ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL;

    EXEC ('UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever')
END

8
হ্যাঁ, আমি এটি বুঝতে পারি। এটি প্রশ্নের উত্তর দেয় না - আমার একই IFব্লকের একটি কলাম তৈরি এবং আপডেট করা দরকার ।
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

@ ওডে: ;এখানে সাহায্য করবে? - আপনি কেবল আপনার উত্তরটি সম্পাদনা করেছেন: ও)
নীল নাইট

@ নীল - হ্যাঁ, এটি আমার চিন্তাভাবনা।
ওলেড

;হয় না কাজ করে - পার্সার এখনও আমাকে "অবৈধ কলামের নাম 'EMP_IS_ADMIN' দিচ্ছে।"
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

যখন ব্যাচটি সংকলিত হয়, EMP_IS_ADMIN এর অস্তিত্ব থাকে না। stackoverflow.com/questions/4855537/...
gbn

17

আপনি চেষ্টা করে দেখতে পারেন sp_executesql, বিভাজন প্রতিটি মধ্যে বিষয়বস্তু GOএকটি পৃথক স্ট্রিং মধ্যে বিবৃতি নিষ্পন্ন করা হবে নীচে উদাহরণে প্রদর্শিত। এছাড়াও, যেখানে একটি ব্যতিক্রম ঘটেছে সহজে ডিবাগিংয়ের জন্য কোন বিবৃতি কার্যকর করা হচ্ছে তা ট্র্যাক করার জন্য একটি @ স্টেটমেন্টের কোনও পরিবর্তনশীল নেই। লাইন নম্বরগুলি ত্রুটির কারণে প্রাসঙ্গিক বিবৃতি সংখ্যার শুরুতে আপেক্ষিক হবে।

BEGIN TRAN

DECLARE @statementNo INT
BEGIN TRY
    IF 1=1
    BEGIN
        SET @statementNo = 1
        EXEC sp_executesql
            N'  ALTER TABLE dbo.EMPLOYEE
                    ADD COLUMN EMP_IS_ADMIN BIT NOT NULL'

        SET @statementNo = 2
        EXEC sp_executesql
            N'  UPDATE dbo.EMPLOYEE
                    SET EMP_IS_ADMIN = 1'

        SET @statementNo = 3
        EXEC sp_executesql
            N'  UPDATE dbo.EMPLOYEE
                    SET EMP_IS_ADMIN = 1x'
    END
END TRY
BEGIN CATCH
    PRINT 'Error occurred on line ' + cast(ERROR_LINE() as varchar(10)) 
       + ' of ' + 'statement # ' + cast(@statementNo as varchar(10)) 
       + ': ' + ERROR_MESSAGE()
    -- error occurred, so rollback the transaction
    ROLLBACK
END CATCH
-- if we were successful, we should still have a transaction, so commit it
IF @@TRANCOUNT > 0
    COMMIT

উপরের উদাহরণে প্রদর্শিত হিসাবে কেবল একক উদ্ধৃতিতে ( ') এ মোড়ানো করে আপনি সহজেই বহু-লাইন বিবৃতিগুলি কার্যকর করতে পারেন । ''স্ক্রিপ্টগুলি তৈরি করার সময় ডাবল একক-উদ্ধৃতি ( ) দিয়ে স্ট্রিংয়ের অভ্যন্তরের যে কোনও একক উক্তিটি পালাতে ভুলবেন না ।


ভাববেন না যে এটি একাধিক লাইনে বিভক্ত কমান্ডগুলির জন্য কাজ করবে, তাই না?
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

@ ব্লুরাজা: এটি কীভাবে কাজ করবে তা প্রদর্শন করার জন্য আমি উদাহরণটি আপডেট করেছি। এই স্ট্রিংগুলি বহু-লাইন হতে পারে, যতক্ষণ না ভিতরে কোনও একক উদ্ধৃতি (') ডাবল-একক উদ্ধৃতি (' ') ব্যবহার করে পালাতে পারে
মেল্লামব্যাক

4
@mellamokb: কঠোরভাবে বলতে, শুধুমাত্র আপডেট চাহিদা sp_executesql ... stackoverflow.com/questions/4855537/...
gbn

4
@ জিবিএন: সত্য। তবে আপনি যদি 100 এর বিবৃতিতে এটি স্বয়ংক্রিয় করতে চলেছেন তবে কখন এবং কোথায় আপনার এটির প্রয়োজন হবে তা সিদ্ধান্ত নেওয়ার পরিবর্তে সমস্ত বিবৃতি জুড়ে অন্ধভাবে এটি প্রয়োগ করা সহজ হবে।
মেল্লামব্যাক

@ জিবিএন @ মেল্লামোকব: আমার মতামত এর মত ছিল SELECT * <newline> FROM whatever। আমি যদি প্রতিটি লাইনকে তার নিজস্ব এক্সেক স্টেটমেন্ট দিয়ে চালিত করি তবে তা ভঙ্গ হবে। বা আপনি কি প্রতিটি GOবক্তব্য ভঙ্গ করার পরামর্শ দিচ্ছেন ?
ব্লুরাজা - ড্যানি প্লেফুঘুফুট

9

আমি শেষ পর্যন্ত GOএটির নিজের লাইনে প্রতিটি উদাহরণ প্রতিস্থাপন করে কাজ করতে পেলাম

END
GO

---Automatic replacement of GO keyword, need to recheck IF conditional:
IF whatever
BEGIN

প্রতিটি গ্রুপের স্টেটমেন্টগুলিকে স্ট্রিংয়ে মুড়িয়ে ফেলার পক্ষে এটি দুর্দান্ত। তবে এটি এখনও আদর্শ থেকে দূরে । যদি কেউ এর থেকে ভাল সমাধান খুঁজে পান তবে এটি পোস্ট করুন এবং আমি তার পরিবর্তে এটি গ্রহণ করব।


6
যদি প্রথম শর্তসাপেক্ষ হয় "যদি এই কলামটি বিদ্যমান না থাকে", ব্লকের প্রথম বিবৃতিটি "এই কলামটি যুক্ত করুন", তবে শর্তাধীন দ্বিতীয় চেকটি কলামটি সন্ধান করবে এবং দ্বিতীয় বিবৃতিটি কার্যকর করবে না
ড্যামিয়েন_এই_বিশ্বাসী

@ দামিয়ান: সত্য; ভাগ্যক্রমে, এটি আমার ক্ষেত্রে কখনই ঘটবে না (শর্তসাপেক্ষে সর্বদা একটি নির্দিষ্ট সারণীতে একটি নির্দিষ্ট মানের জন্য যাচাই করা হয়, যা সর্বদা IFব্লকের সর্বশেষ বিবৃতি হিসাবে যুক্ত করা হয় )। দেখে মনে হচ্ছে এসকিউএল এ করার কোনও ভাল উপায় নেই।
ব্লুরাজা - ড্যানি পিফ্লুঘুফুট

মিনা জ্যাকব এর set noexecউত্তর কেবলমাত্র এখন পর্যন্ত এসএস SQLCMDমোড স্ক্রিপ্টে (যেমন একটি মাস্টার ডিপ্লোয়মেন্ট স্ক্রিপ্ট) ব্যবহারের জন্য বাস্তব উত্তর :rযা সেই ifবিবৃতিতে কিছু কলের সাথে অন্য এসএস স্ক্রিপ্টগুলি (অর্থাৎ উপ-স্থাপনামূলক স্ক্রিপ্ট) কল করে ( কমান্ডের মাধ্যমে ) । ওডেস, মেল্লামব্যাক এবং অ্যান্ডি জোয়ারারের কলগুলি / - এর সমস্ত বিবৃতি বন্ধ করে দেওয়ার উত্তরগুলি অ-স্টার্টার নয়। এছাড়াও, বিবৃতি (উদাহরণস্বরূপ এর আগে একটি স্পষ্টের প্রয়োজন হয় ) থাকলে - পদ্ধতিটি কাজ করবে না । execbeginendbeginendcreatego
টম

8

আপনি জিবি ইনবিটউইনের পরিবর্তে বিগইন এবং এন্ডে স্টেটমেন্টগুলি আবদ্ধ করতে পারেন

IF COL_LENGTH('Employees','EMP_IS_ADMIN') IS NULL --Column does not exist
BEGIN
    BEGIN
        ALTER TABLE dbo.Employees ADD EMP_IS_ADMIN BIT
    END

    BEGIN
        UPDATE EMPLOYEES SET EMP_IS_ADMIN = 0
    END
END

(নর্থওয়াইন্ড ডাটাবেসে পরীক্ষিত)

সম্পাদনা: (সম্ভবত এসকিউএল ২০১২ এ পরীক্ষা করা হয়েছে)



4
কেন এটি নিম্নচক্ষিত হয়েছিল জানি না ... আমার জন্য কবজির মতো কাজ করে।
থোররিন

10
এসকিউএল সার্ভার ২০০৮ আর 2 ব্যবহার করে, এটি আমার পক্ষে কাজ করে না বলে মনে হচ্ছে, আমি এখনও একটি ত্রুটি পেয়েছি 'অবৈধ কলামের নাম' EMP_IS_ADMIN '' ' আপডেট লাইনে
মেরিকোওয়া

বিগইন-এন্ড ব্যাচিং এসকিউএল সার্ভার 2016 ব্যবহার করে আমার জন্য কাজ করেছিল IM আইএমও এটিই সবচেয়ে পরিষ্কার বাক্য গঠন।
উবার শনজ

মিনা জ্যাকব এর set noexecউত্তরটি এখন পর্যন্ত কেবলমাত্র এসএস মোড স্ক্রিপ্টে (যেমন একটি মাস্টার ডিপ্লোয়মেন্ট স্ক্রিপ্ট) ব্যবহারের জন্য কেবলমাত্র বাস্তব উত্তর যা সেই বিবৃতিতে কিছু কলের সাথে অন্য এসএস স্ক্রিপ্টগুলি (অর্থাৎ উপ-স্থাপনামূলক স্ক্রিপ্ট) SQLCMDকল করে ( :rকমান্ডের মাধ্যমে ) if। ওডেস, মেল্লামব্যাক এবং অ্যান্ডি জোয়ারারের কলগুলি / - এর সমস্ত বিবৃতি বন্ধ করে দেওয়ার উত্তরগুলি অ-স্টার্টার নয়। এছাড়াও, বিবৃতি (উদাহরণস্বরূপ এর আগে একটি স্পষ্টের প্রয়োজন হয় ) থাকলে - পদ্ধতিটি কাজ করবে না । execbeginendbeginendcreatego
টম

1

আপনি এই সমাধান চেষ্টা করতে পারেন:

if exists(
SELECT...
)
BEGIN
PRINT 'NOT RUN'
RETURN
END

--if upper code not true

ALTER...
GO
UPDATE...
GO

4
খুব কার্যকর না যদি আপনার একের পর এক বেশ কয়েকটি ব্লক থাকে, তাই না?
জেরি

0

আমি এর RAISERRORজন্য অতীতে ব্যবহার করেছি

IF NOT whatever BEGIN
    RAISERROR('YOU''RE ALL SET, and sorry for the error!', 20, -1) WITH LOG
END

ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL
GO
UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever

-1

কোড ছাড়ার জন্য আপনি একটি GOTOএবং LABELবিবৃতিগুলি অন্তর্ভুক্ত করতে পারেন , GOকীওয়ার্ডটি অক্ষত রেখে ।


6
দেখে মনে হচ্ছে যে লেবেলগুলি এসকিউএল পাঠানো ব্যাচে নেই বলে জিও স্টেটমেন্টগুলিতে রেফারেন্স দেওয়া যাবে না
বার্কলেব্রস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.