كيف أقوم بإنشاء إجراء مخزن بشكل مشروط في SQL Server؟

StackOverflow https://stackoverflow.com/questions/55506

  •  09-06-2019
  •  | 
  •  

سؤال

كجزء من استراتيجية التكامل الخاصة بي، لدي عدد قليل من نصوص SQL التي يتم تشغيلها لتحديث قاعدة البيانات.أول شيء تفعله كل هذه البرامج النصية هو التحقق لمعرفة ما إذا كانت بحاجة إلى التشغيل، على سبيل المثال:

if @version <> @expects
    begin
        declare @error varchar(100);
        set @error = 'Invalid version. Your version is ' + convert(varchar, @version) + '. This script expects version ' + convert(varchar, @expects) + '.';
        raiserror(@error, 10, 1);
    end
else
    begin
        ...sql statements here...
    end

يعمل بشكل رائع!إلا إذا كنت بحاجة إلى إضافة إجراء مخزن.يجب أن يكون الأمر "إنشاء proc" هو الأمر الوحيد في مجموعة أوامر SQL.يؤدي وضع "إنشاء proc" في عبارة IF الخاصة بي إلى حدوث هذا الخطأ:

'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.

أوه!كيف أضع أمر CREATE PROC في البرنامج النصي الخاص بي، وأقوم بتنفيذه فقط إذا لزم الأمر؟

هل كانت مفيدة؟

المحلول

وهنا ما توصلت إليه:

لفها في EXEC()، مثل ذلك:

if @version <> @expects
    begin
        ...snip...
    end
else
    begin
        exec('CREATE PROC MyProc AS SELECT ''Victory!''');
    end

يعمل كالسحر!

نصائح أخرى

يعد SET NOEXEC ON طريقة جيدة لإيقاف تشغيل جزء من التعليمات البرمجية

IF NOT EXISTS (SELECT * FROM sys.assemblies WHERE name = 'SQL_CLR_Functions')
  SET NOEXEC ON
GO
CREATE FUNCTION dbo.CLR_CharList_Split(@list nvarchar(MAX), @delim nchar(1) = N',')
RETURNS TABLE (str nvarchar(4000)) AS EXTERNAL NAME SQL_CLR_Functions.[Granite.SQL.CLR.Functions].CLR_CharList_Split
GO
SET NOEXEC OFF

وجدت هنا:https://codereview.stackexchange.com/questions/10490/conditional-create-must-be-the-only-statement-in-the-batch

ملاحظة.يتم تعيين طريقة أخرى parseonly {on | عن }.

لكن انتبه إلى علامات الاقتباس المفردة ضمن الإجراء المُخزن لديك - فيجب "التخلص منها" عن طريق إضافة علامة اقتباس ثانية.الإجابة الأولى فعلت هذا، ولكن فقط في حالة فاتك ذلك.فخ للاعبين الشباب.

يعد إصدار قاعدة بياناتك هو الحل الأمثل، ولكن...لماذا يتم إنشاء الإجراءات المخزنة بشكل مشروط.بالنسبة لطرق العرض والإجراءات المخزنة والوظائف، ما عليك سوى إسقاطها بشكل مشروط وإعادة إنشائها في كل مرة.إذا قمت بالإنشاء بشكل مشروط، فلن تقوم بتنظيف قواعد البيانات التي بها مشكلة أو اختراق تم وضعه منذ عامين بواسطة مطور آخر (أنت أو أنا لن نفعل ذلك أبدًا) والذي كان متأكدًا من أنه سيتذكر إزالة هذه المشكلة مرة واحدة تحديث الطوارئ.

مشكلة الإسقاط والإنشاء هي أنك تفقد أي منح أمنية تم تطبيقها مسبقًا على الكائن الذي يتم إسقاطه.

يجب أن أعترف أنني أتفق عادةً مع Peter - فأنا أسقط بشكل مشروط ثم أعيد إنشائه دون قيد أو شرط في كل مرة.لقد تم اكتشافي مرات عديدة في الماضي عندما كنت أحاول تخمين اختلافات المخطط بين قواعد البيانات، مع أو بدون أي شكل من أشكال التحكم في الإصدار.

بعد قولي هذا، فإن اقتراحك @Josh رائع جدًا.بالتأكيد مثيرة للاهتمام.:-)

هذا موضوع قديم، لكن جوبو غير صحيح:يجب أن يكون إجراء الإنشاء هو البيان الأول في الدفعة.لذلك، لا يمكنك استخدام Exists لاختبار وجود ومن ثم استخدام أي منهما Create أو Alter.شفقة.

الحل الخاص بي هو التحقق من وجود proc، إذا كان الأمر كذلك، فقم بإسقاطه، ثم قم بإنشاء proc (نفس إجابةrobsoft ولكن مع مثال ...)

IF EXISTS(SELECT * FROM sysobjects WHERE Name = 'PROC_NAME' AND xtype='P') 
BEGIN
    DROP PROCEDURE PROC_NAME
END
GO
CREATE PROCEDURE PROC_NAME
    @value  int
AS
BEGIN
    UPDATE  SomeTable
    SET     SomeColumn = 1
    WHERE   Value = @value
END
GO

استخدم الأمر "موجود" في T-SQL لمعرفة ما إذا كان الإجراء المخزن موجودًا.إذا كان الأمر كذلك، استخدم "تغيير"، وإلا استخدم "إنشاء"

IF NOT EXISTS(SELECT * FROM sys.procedures WHERE name = 'pr_MyStoredProc')
BEGIN

     CREATE PROCEDURE pr_MyStoredProc AS .....
     SET NOCOUNT ON
END

ALTER PROC pr_MyStoredProc
AS
SELECT * FROM tb_MyTable
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top