كيف أقوم بإنشاء إجراء مخزن بشكل مشروط في SQL Server؟
-
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
ملاحظة.يتم تعيين طريقة أخرى 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