سؤال

هل هناك طريقة لإيقاف تنفيذ برنامج SQL النصي في خادم SQL فورًا، مثل أمر "فاصل" أو "خروج"؟

لدي برنامج نصي يقوم ببعض عمليات التحقق من الصحة وعمليات البحث قبل أن يبدأ في إجراء عمليات الإدراج، وأريد أن يتوقف في حالة فشل أي من عمليات التحقق من الصحة أو عمليات البحث.

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

المحلول

ال com.Raiserror طريقة

raiserror('Oh no a fatal error', 20, -1) with log

سيؤدي هذا إلى إنهاء الاتصال، وبالتالي إيقاف تشغيل بقية البرنامج النصي.

لاحظ أن كلا من مستوى الخطورة 20 أو أعلى و WITH LOG الخيار ضروري للعمل بهذه الطريقة.

وهذا يعمل حتى مع عبارات GO، على سبيل المثال.

print 'hi'
go
raiserror('Oh no a fatal error', 20, -1) with log
go
print 'ho'

سوف أعطيك الإخراج:

hi
Msg 2745, Level 16, State 2, Line 1
Process ID 51 has raised user error 50000, severity 20. SQL Server is terminating this process.
Msg 50000, Level 20, State 1, Line 1
Oh no a fatal error
Msg 0, Level 20, State 0, Line 0
A severe error occurred on the current command.  The results, if any, should be discarded.

لاحظ أن "ho" لم تتم طباعته.

تحفظات:

  • يعمل هذا فقط إذا قمت بتسجيل الدخول كمسؤول (دور "مسؤول النظام")، ويتركك أيضًا بدون اتصال بقاعدة البيانات.
  • إذا لم تقم بتسجيل الدخول كمسؤول، فسوف يفشل استدعاء RAISEERROR() نفسه وسيستمر تنفيذ البرنامج النصي.
  • عند استدعائه باستخدام sqlcmd.exe، سيتم الإبلاغ عن رمز الخروج 2745.

مرجع: http://www.mydatabasesupport.com/forums/ms-sqlserver/174037-sql-server-2000-abort-whole-script.html#post761334

طريقة noexec

هناك طريقة أخرى تعمل مع عبارات GO وهي set noexec on.يؤدي هذا إلى تخطي بقية البرنامج النصي.لا ينهي الاتصال، ولكن عليك أن تتحول noexec مرة أخرى قبل تنفيذ أي أوامر.

مثال:

print 'hi'
go

print 'Fatal error, script will not continue!'
set noexec on

print 'ho'
go

-- last line of the script
set noexec off -- Turn execution back on; only needed in SSMS, so as to be able 
               -- to run this script again in the same session.

نصائح أخرى

ومجرد استخدام RETURN (انها ستعمل على حد سواء داخل وخارج إجراء مخزن).

إذا يمكنك استخدام وضع SQLCMD، ثم التعويذة

:on error exit

و(بما في ذلك القولون) سوف يسبب RAISERROR لوقف الواقع النصي. منها مثلا.

:on error exit

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SOMETABLE]') AND type in (N'U')) 
    RaisError ('This is not a Valid Instance Database', 15, 10)
GO

print 'Keep Working'

وإرادة الإخراج:

Msg 50000, Level 15, State 10, Line 3
This is not a Valid Instance Database
** An error was encountered during execution of batch. Exiting.

ووسوف دفعة تتوقف. إذا لم يتم تشغيل وضع SQLCMD على، ستحصل على خطأ في التحليل حول القولون. أونفورتوانتيلي، انها ليست من الرصاص تماما كما لو يتم تشغيل البرنامج النصي دون أن يكون في وضع SQLCMD، النسائم SQL الأدارة ستوديو الحق في الماضي حتى تحليل أخطاء وقت! ومع ذلك، إذا كنت تشغيلها من سطر الأوامر، وهذا على ما يرام.

وأنا لن تستخدم RAISERROR- SQL ديه IF البيانات التي يمكن استخدامها لهذا الغرض. هل التحقق من الصحة وعمليات البحث وتحديد المتغيرات المحلية، ثم استخدام قيمة المتغيرات في عبارات IF لجعل إدراج مشروطة.

وأنت لا تحتاج إلى التحقق ومتغيرة نتيجة كل اختبار التحقق من الصحة. وعادة ما كنت تستطيع أن تفعل هذا مع متغير راية واحدة فقط لتأكيد كل الظروف مرت:

declare @valid bit

set @valid = 1

if -- Condition(s)
begin
  print 'Condition(s) failed.'
  set @valid = 0
end

-- Additional validation with similar structure

-- Final check that validation passed
if @valid = 1
begin
  print 'Validation succeeded.'

  -- Do work
end

وحتى لو التحقق من الصحة أكثر تعقيدا، يجب عليك سوى عدد قليل من المتغيرات العلم أن تدرج في الاختيار النهائي الخاص بك (ق).

وأنا مدد noexec على / قبالة حل بنجاح مع الصفقة لتشغيل البرنامج النصي في كل شيء أو لا شيء الطريقة.

set noexec off

begin transaction
go

<First batch, do something here>
go
if @@error != 0 set noexec on;

<Second batch, do something here>
go
if @@error != 0 set noexec on;

<... etc>

declare @finished bit;
set @finished = 1;

SET noexec off;

IF @finished = 1
BEGIN
    PRINT 'Committing changes'
    COMMIT TRANSACTION
END
ELSE
BEGIN
    PRINT 'Errors occured. Rolling back changes'
    ROLLBACK TRANSACTION
END

ويبدو أن المترجم "يفهم" المتغيرfinished في IF، حتى لو كان هناك خطأ وتم تعطيل التنفيذ. ومع ذلك، يتم تعيين القيمة إلى 1 فقط إذا لم يتم تعطيل التنفيذ. ومن هنا أنا لطيف أن تلتزم أو التراجع عن الصفقة وفقا لذلك.

هل يمكن أن التفاف بيان SQL الخاصة بك في حلقة WHILE واستخدام BREAK إذا لزم الأمر

WHILE 1 = 1
BEGIN
   -- Do work here
   -- If you need to stop execution then use a BREAK


    BREAK; --Make sure to have this break at the end to prevent infinite loop
END

في SQL 2012+، يمكنك استخدام THROW .

THROW 51000, 'Stopping execution because validation failed.', 0;
PRINT 'Still Executing'; -- This doesn't execute with THROW

ومن MSDN:

<اقتباس فقرة>   

ويرفع عملية إعدام استثناء، ونقل إلى كتلة CATCH لبناء TRY ... CATCH ... إذا كان بناء TRY ... CATCH غير متوفر، يتم إنهاء الدورة. يتم تعيين رقم السطر والإجراءات حيث يتم رفع استثناء. تم تعيين شدة إلى 16.

هل هذا الإجراء المخزن؟ إذا كان الأمر كذلك، أعتقد أنك يمكن أن مجرد القيام العودة، مثل "العودة NULL"؛

وعلاوة على ذلك refinig طريقة Sglasses، الأسطر أعلاه فرض استخدام وضع SQLCMD، وإما treminates وscirpt إذا لم تكن تستخدم وضع SQLCMD أو يستخدم :on error exit للخروج على خطأ أي
CONTEXT_INFO يستخدم لتتبع الدولة.

SET CONTEXT_INFO  0x1 --Just to make sure everything's ok
GO 
--treminate the script on any error. (Requires SQLCMD mode)
:on error exit 
--If not in SQLCMD mode the above line will generate an error, so the next line won't hit
SET CONTEXT_INFO 0x2
GO
--make sure to use SQLCMD mode ( :on error needs that)
IF CONTEXT_INFO()<>0x2 
BEGIN
    SELECT CONTEXT_INFO()
    SELECT 'This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!'
    RAISERROR('This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!',16,1) WITH NOWAIT 
    WAITFOR DELAY '02:00'; --wait for the user to read the message, and terminate the script manually
END
GO

----------------------------------------------------------------------------------
----THE ACTUAL SCRIPT BEGINS HERE-------------

وأود أن أقترح عليك أن التفاف كتلة الرمز المناسب في كتلة محاولة الصيد. ثم يمكنك استخدام هذا الحدث RAISERROR مع خطورة من 11 من أجل كسر لكتلة التقاط إذا كنت ترغب في ذلك. إذا كنت ترغب فقط في raiserrors لكن متابعة تنفيذ داخل كتلة المحاولة ثم استخدام شدة أقل.

تأكد معنى؟

وابتهاج، جون

[قام لتشمل BOL المرجعي]

http://msdn.microsoft.com/en -US / مكتبة / ms175976 (SQL.90) .aspx اتصال

يمكنك تغيير تدفق التنفيذ باستخدام عبارات GOTO :

IF @ValidationResult = 0
BEGIN
    PRINT 'Validation fault.'
    GOTO EndScript
END

/* our code */

EndScript:

ويمكنك استخدام RAISERROR .

لا شيء من هذه يعمل مع عبارات "GO".في هذا الرمز، بغض النظر عما إذا كانت درجة الخطورة 10 أو 11، فإنك تحصل على بيان الطباعة النهائي.

اختبار كتابي:

-- =================================
PRINT 'Start Test 1 - RAISERROR'

IF 1 = 1 BEGIN
    RAISERROR('Error 1, level 11', 11, 1)
    RETURN
END

IF 1 = 1 BEGIN
    RAISERROR('Error 2, level 11', 11, 1)
    RETURN
END
GO

PRINT 'Test 1 - After GO'
GO

-- =================================
PRINT 'Start Test 2 - Try/Catch'

BEGIN TRY
    SELECT (1 / 0) AS CauseError
END TRY
BEGIN CATCH
    SELECT ERROR_MESSAGE() AS ErrorMessage
    RAISERROR('Error in TRY, level 11', 11, 1)
    RETURN
END CATCH
GO

PRINT 'Test 2 - After GO'
GO

نتائج:

Start Test 1 - RAISERROR
Msg 50000, Level 11, State 1, Line 5
Error 1, level 11
Test 1 - After GO
Start Test 2 - Try/Catch
 CauseError
-----------

ErrorMessage
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Divide by zero error encountered.

Msg 50000, Level 11, State 1, Line 10
Error in TRY, level 11
Test 2 - After GO

الطريقة الوحيدة لإنجاز هذا العمل هي كتابة السيناريو بدونه GO صياغات.في بعض الأحيان يكون ذلك سهلا.في بعض الأحيان يكون الأمر صعبًا للغاية.(استخدم شيئًا مثل IF @error <> 0 BEGIN ....)

وهذا هو بلدي الحل:

...

BEGIN
    raiserror('Invalid database', 15, 10)
    rollback transaction
    return
END

ويمكنك استخدام بيان GOTO. جرب هذا. هذا هو استخدام كامل بالنسبة لك.

WHILE(@N <= @Count)
BEGIN
    GOTO FinalStateMent;
END

FinalStatement:
     Select @CoumnName from TableName

وأنا استخدم RETURN هنا في كل وقت، ويعمل في البرنامج النصي أو Stored Procedure

تأكد من أنك ROLLBACK الصفقة إذا كنت في واحدة، وإلا RETURN على الفور سوف يؤدي إلى معاملة غير ملتزم بها مفتوحة

وتشك عن الجواب!

وraiserror() يعمل بشكل جيد ولكن يجب أن لا ننسى بيان return خلاف ذلك يستمر البرنامج النصي بدون خطأ! (hense وRAISERROR ليست "throwerror" ؛-))، وبالطبع بعمل التراجع إذا لزم الأمر.

وraiserror() من الجميل أن تخبر الشخص الذي يقوم بتنفيذ السيناريو الذي حدث خطأ ما.

إذا كنت ببساطة تنفيذ برنامج نصي في إدارة Studio، وتريد إيقاف التنفيذ أو التراجع عن الصفقة (في حال استخدامها) في الخطأ الأول، بعد ذلك الطريق جيد أعتقد هو استخدام كتلة التقاط محاولة (SQL 2005 فصاعدا). هذا يعمل بشكل جيد في الاستوديو إدارة إذا كنت تنفيذ ملف البرنامج النصي. يمكن تخزينها بروك دائما استخدام هذا أيضا.

في الماضي استخدمنا ما يلي...عمل بشكل أفضل:

RAISERROR ('Error! Connection dead', 20, 127) WITH LOG
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top