কীভাবে কোনও এসকিউএল সার্ভার ব্যবহারকারী-সংজ্ঞায়িত ফাংশন থেকে ত্রুটির প্রতিবেদন করবেন


146

আমি এসকিউএল সার্ভার ২০০৮-এ একটি ব্যবহারকারী-সংজ্ঞায়িত ফাংশন লিখছি I আমি জানি যে ফাংশনগুলি স্বাভাবিক উপায়ে ত্রুটি বাড়িয়ে তুলতে পারে না - আপনি যদি রেসারার বিবৃতি এসকিউএল ফেরত অন্তর্ভুক্ত করার চেষ্টা করেন:

Msg 443, Level 16, State 14, Procedure ..., Line ...
Invalid use of a side-effecting operator 'RAISERROR' within a function.

তবে আসল বিষয়টি হ'ল ফাংশনটি কিছু ইনপুট নেয়, যা অবৈধ হতে পারে এবং যদি তা হয় তবে কোনও কার্যকর অর্থই ফাংশনটি ফিরে আসতে পারে না। আমি তখন কি করব?

আমি অবশ্যই অবশ্যই NULL ফিরিয়ে দিতে পারি, তবে যে কোনও বিকাশকারীর পক্ষে ফাংশনটি ব্যবহার করে এটির সমস্যা সমাধান করা কঠিন হবে। আমি শূন্য বা এরকম কিছু দ্বারা বিভাজনও ঘটতে পারি - এটি একটি ত্রুটি বার্তা উত্পন্ন করবে তবে একটি বিভ্রান্তিমূলক। আমার নিজের ত্রুটি বার্তাটি কোনওভাবে রিপোর্ট করার কোনও উপায় আছে কি?

উত্তর:


223

অর্থপূর্ণ ত্রুটি ছুঁড়তে আপনি CAST ব্যবহার করতে পারেন:

create function dbo.throwError()
returns nvarchar(max)
as
begin
    return cast('Error happened here.' as int);
end

তারপরে এসকিএল সার্ভার কিছু সাহায্যের তথ্য প্রদর্শন করবে:

Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the varchar value 'Error happened here.' to data type int.

112
দুর্দান্ত উত্তর, তবে জেইজেড ওয়াটটা হ্যাক। > :(
জনল 4

5
একটি ইনলাইন-টেবিল-মূল্যযুক্ত-ক্রিয়াকলাপের জন্য যেখানে প্রত্যাবর্তন একটি সাধারণ নির্বাচন, সেখানে একা কাজ করে না কারণ কিছুই ফেরানো হয় না - এমনকি শূন্যও হয় না, এবং আমার ক্ষেত্রে যখন কিছুই পাওয়া যায় না তখন আমি একটি ত্রুটি ছুঁড়ে মারতে চাইতাম। স্পষ্ট পারফরম্যান্সের কারণে আমি ইনলাইন ফাংশনটিকে একটি বহু-স্টেটমেন্টের মধ্যে ভাঙ্গতে চাইনি। পরিবর্তে আমি আপনার সমাধান প্লাস ISNULL এবং MAX ব্যবহার করেছি। রিটার্নের স্ট্যাটামেন্টটি এখন এর মতো দেখাচ্ছে: নির্বাচন করুন নির্বাচন করুন (ম্যাক্স (E.EntityID), CAST ('চেহারাটি (' + @ লকআপটি পরিবর্তনশীল + ') বিদ্যমান নেই Int' হিসাবে অন্তর্ভুক্ত)) [এনটিটিআইডি] সত্ত্বা থেকে ই যেখানে যেখানে ই। লুকআপ = @ লুকআপ পরিবর্তনশীল
মাইকটিভি 3'12

হ্যাঁ, আপনি একটি ত্রুটি ফেলতে পারেন তবে মনে হচ্ছে আপনি শর্তাধীন কোনও ত্রুটি ছুঁড়ে ফেলতে পারেন। কোড পথ নির্বিশেষে ফাংশনটি কার্যকর করা হয়।
সাতনহক

10
দুর্দান্ত সমাধান, তবে যারা টিভিএফ ব্যবহার করছেন তাদের পক্ষে এটি সহজেই ফিরতি অংশ হতে পারে না। তাদের জন্য:declare @error int; set @error = 'Error happened here.';
টিম লেহনার

20
এক হাজার জ্বলন্ত সূর্যের শক্তি দিয়ে আমি এটিকে ঘৃণা করি। অন্য কোন বিকল্প নেই? ফাইন। তবে ক্রপস ...
রেমি ডেস্প্রেস-স্মিথ

18

স্বাভাবিক কৌশলটি 0 দ্বারা একটি বিভাজনকে বাধ্য করা হয় এটি একটি ত্রুটি বাড়াবে এবং বর্তমান বিবৃতিতে বাধা দেবে যা ফাংশনটি মূল্যায়ন করছে। যদি বিকাশকারী বা সহায়তাকারী ব্যক্তি এই আচরণ সম্পর্কে জেনে থাকেন তবে সমস্যাটি তদন্ত ও সমস্যা সমাধান করা মোটামুটি সহজ কারণ 0 ত্রুটি দ্বারা বিভাজনটি একটি ভিন্ন, সম্পর্কিত সম্পর্কযুক্ত সমস্যার লক্ষণ হিসাবে বোঝা যায়।

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


7

ভ্লাদিমির কোরোলেভের উত্তর অনুসরণ করে শর্তসাপেক্ষে একটি ত্রুটি ছোঁড়ার প্রতিমাটি

CREATE FUNCTION [dbo].[Throw]
(
    @error NVARCHAR(MAX)
)
RETURNS BIT
AS
BEGIN
    RETURN CAST(@error AS INT)
END
GO

DECLARE @error NVARCHAR(MAX)
DECLARE @bit BIT

IF `error condition` SET @error = 'My Error'
ELSE SET @error = '0'

SET @bit = [dbo].[Throw](@error)    

6

আমি মনে করি সবচেয়ে পরিষ্কার উপায় হ'ল এটি মেনে নেওয়া যায় যে যদি অবৈধ যুক্তিগুলি পাস করা হয় তবে ফাংশনটি NULL ফিরিয়ে দিতে পারে। যতক্ষণ এটি স্পষ্টভাবে নথিভুক্ত হয় তবে এটি ঠিক রাখা উচিত?

-- =============================================
-- Author: AM
-- Create date: 03/02/2010
-- Description: Returns the appropriate exchange rate
-- based on the input parameters.
-- If the rate cannot be found, returns NULL
-- (RAISEERROR can't be used in UDFs)
-- =============================================
ALTER FUNCTION [dbo].[GetExchangeRate] 
(
    @CurrencyFrom char(3),
    @CurrencyTo char(3),
    @OnDate date
)
RETURNS decimal(18,4)
AS
BEGIN

  DECLARE @ClosingRate as decimal(18,4)

    SELECT TOP 1
        @ClosingRate=ClosingRate
    FROM
        [FactCurrencyRate]
    WHERE
        FromCurrencyCode=@CurrencyFrom AND
        ToCurrencyCode=@CurrencyTo AND
        DateID=dbo.DateToIntegerKey(@OnDate)

    RETURN @ClosingRate 

END
GO

5

RAISEERRORবা @@ERRORইউডিএফগুলিতে অনুমোদিত নয়। আপনি কি ইউডিএফটিকে একটি স্টোরড পদ্ধতিতে পরিণত করতে পারেন?

এসকিউএল সার্ভারে এরল্যান্ড সোমমারস্কোগের নিবন্ধটি ত্রুটি পরিচালনা করার মাধ্যমে - একটি পটভূমি :

ব্যবহারকারী-সংজ্ঞায়িত ফাংশনগুলি সাধারণত একটি সেট, নির্বাচন, অন্তর্ভুক্ত, আপডেট বা বিবৃতি মুছে ফেলার অংশ হিসাবে ডাকা হয়। আমি যা পেয়েছি তা হ'ল যদি কোনও বহু-বিবৃতি টেবিল-মূল্যযুক্ত ফাংশনে বা কোনও স্কেলারের ফাংশনে কোনও ত্রুটি উপস্থিত হয় তবে ফাংশনটির সম্পাদনা অবিলম্বে বাতিল করা হয়, এবং একইভাবে বিবৃতিটি অংশটির অংশ। ত্রুটিটি ব্যাচটি বাতিল না করা পর্যন্ত পরবর্তী লাইনে কার্যকর করা চালানো হয়। উভয় ক্ষেত্রেই, @@ ত্রুটি 0 টি। সুতরাং, টি-এসকিউএল থেকে কোনও ফাংশনে ত্রুটি ঘটেছে তা সনাক্ত করার কোনও উপায় নেই।

সমস্যাটি ইনলাইন টেবিল-ফাংশনগুলির সাথে উপস্থিত হয় না, যেহেতু একটি ইনলাইন টেবিল-মূল্যযুক্ত ফাংশন মূলত একটি ম্যাক্রো যা ক্যোয়ারী প্রসেসর ক্যোয়ারীতে পোস্ট করে।

আপনি এক্সেক স্টেটমেন্ট দিয়ে স্কেলার ফাংশনগুলিও সম্পাদন করতে পারেন। এই ক্ষেত্রে, কোনও ত্রুটি দেখা দিলে কার্যকর করা চলতে থাকে (যদি না এটি ব্যাচ-গর্ভাবস্থার ত্রুটি হয়)। @@ ত্রুটি সেট করা আছে, এবং আপনি ফাংশনের মধ্যে @@ ত্রুটির মান পরীক্ষা করতে পারেন। যদিও কলারের সাথে ত্রুটিটি যোগাযোগ করা সমস্যাযুক্ত হতে পারে।


4

শীর্ষের উত্তরটি সাধারণত সেরা, তবে ইনলাইন টেবিলের মূল্যবান ফাংশনের জন্য কাজ করে না।

মাইকটিভি শীর্ষ উত্তরের মন্তব্যে এর জন্য একটি সমাধান দিয়েছেন, তবে এটির জন্য ম্যাক্সের মতো একটি সামগ্রিক ফাংশন ব্যবহার করা দরকার যা আমার পরিস্থিতিতে ভালভাবে কাজ করে নি।

আমি মামলার বিকল্প বিকল্পটি দিয়ে গোল করলাম যেখানে আপনার একটি ইনলাইন টেবিলের মূল্যবান ইউডিএফ দরকার যা একটি সামগ্রীর পরিবর্তে সিলেক্ট * এর মতো কিছু ফেরত দেয় । এই নির্দিষ্ট ক্ষেত্রে সমাধানের নমুনা কোড নীচে is যেহেতু কেউ ইতিমধ্যে চিহ্নিত করেছে ... "জিজি ওয়াটা হ্যাক" :) আমি এই মামলার আরও ভাল সমাধানকে স্বাগত জানাই!

create table foo (
    ID nvarchar(255),
    Data nvarchar(255)
)
go

insert into foo (ID, Data) values ('Green Eggs', 'Ham')
go

create function dbo.GetFoo(@aID nvarchar(255)) returns table as return (
    select *, 0 as CausesError from foo where ID = @aID

    --error checking code is embedded within this union
    --when the ID exists, this second selection is empty due to where clause at end
    --when ID doesn't exist, invalid cast with case statement conditionally causes an error
    --case statement is very hack-y, but this was the only way I could get the code to compile
    --for an inline TVF
    --simpler approaches were caught at compile time by SQL Server
    union

    select top 1 *, case
                        when ((select top 1 ID from foo where ID = @aID) = @aID) then 0
                        else 'Error in GetFoo() - ID "' + IsNull(@aID, 'null') + '" does not exist'
                    end
    from foo where (not exists (select ID from foo where ID = @aID))
)
go

--this does not cause an error
select * from dbo.GetFoo('Green Eggs')
go

--this does cause an error
select * from dbo.GetFoo('Yellow Eggs')
go

drop function dbo.GetFoo
go

drop table foo
go

1
যে কারও পড়ার জন্য, আমি সম্ভাব্য পারফরম্যান্সের প্রভাবগুলির দিকে তাকাতে পারি নি ... হ্যাক ইউনিয়ন + কেস স্টেটমেন্টটি কিছুটা ধীরে ধীরে কমিয়ে দিলে আমি অবাক হব না ...
ডেভেক

4

কয়েকজন লোক টেবিল-মূল্যবান ফাংশনগুলিতে ত্রুটি বাড়াতে বলছিল, যেহেতু আপনি " রিটার্ন [অবৈধ castালাই] " বাছাই করতে পারবেন না । একটি চলকটিতে অবৈধ কাস্টকে বরাদ্দ করা ঠিক তেমনি কাজ করে।

CREATE FUNCTION fn()
RETURNS @T TABLE (Col CHAR)  
AS
BEGIN

DECLARE @i INT = CAST('booooom!' AS INT)  

RETURN

END

এর ফলে:

এমএসজি 245, স্তর 16, রাজ্য 1, লাইন 14 রূপান্তরটি ব্যর্থ হয়েছে যখন বর্ণের মান 'বুম!' রূপান্তর করার সময় ব্যর্থ হয়েছে! তথ্য টাইপ int।


2

আমি টেবিলের মূল্যবান ফাংশন সম্পর্কিত ডেভেকের উত্তরে মন্তব্য করতে পারি না, তবে আমার বিনীত মতে এটি সহজ সমাধান:

CREATE FUNCTION dbo.ufn_test (@a TINYINT)
RETURNS @returns TABLE(Column1 VARCHAR(10), Value1 TINYINT)
BEGIN
    IF @a>50 -- if @a > 50 - raise an error
    BEGIN
      INSERT INTO @returns (Column1, Value1)
      VALUES('error','@a is bigger than 50!') -- reminder Value1 should be TINYINT
    END

    INSERT INTO @returns (Column1, Value1)
    VALUES('Something',@a)
    RETURN;
END

SELECT Column1, Value1 FROM dbo.ufn_test(1) -- this is okay
SELECT Column1, Value1 FROM dbo.ufn_test(51) -- this will raise an error

-3

একটি উপায় (একটি হ্যাক) একটি ফাংশন / সঞ্চিত প্রক্রিয়া যা একটি অবৈধ ক্রিয়া সম্পাদন করে। উদাহরণস্বরূপ, নিম্নলিখিত সিউডো এসকিউএল

create procedure throw_error ( in err_msg varchar(255))
begin
insert into tbl_throw_error (id, msg) values (null, err_msg);
insert into tbl_throw_error (id, msg) values (null, err_msg);
end;

যেখানে tbl_throw_error টেবিলটিতে রয়েছে, কলামে err_msg এ একটি অনন্য বাধা রয়েছে। এর একটি পার্শ্ব-প্রতিক্রিয়া (কমপক্ষে মাইএসকিউএল এ) হ'ল এরর_এমএসজি এর মানটি প্রয়োগ স্তরের ব্যতিক্রম বস্তুতে ফিরে এলে ব্যতিক্রমের বিবরণ হিসাবে ব্যবহৃত হয়।

আপনি এসকিউএল সার্ভারের সাথে অনুরূপ কিছু করতে পারেন কিনা তা আমি জানি না তবে এটির জন্য একটি মূল্য রয়েছে।


5
আকর্ষণীয় ধারণা, তবে INSERT এর কোনও কার্যক্রমে অনুমোদিত নয়।
EMP
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.