Anticipate a CAST failure?

  • Is there a simple way to anticipate a doomed CAST operation, or trap the resulting error, clear the error and exit?

    In context ...

    I am passing data of type uniqueidentifier as a parameter in a VB ADO Command. I prefer to store this parameter as a string on the VB side

    (i.e. '111BB228-66CE-4A72-85D5-0A61F38C961')

    and so really I am passing a string parameter, which I convert in the stored procedure, e.g.

    CREATE PROCEDURE up_wwwValidateSessionGUID @vcrSessionGUID varchar(36)

    AS

    DECLARE @guidSessionGUID as uniqueidentifier

    SET @guidSessionGUID=CAST(@vcrSessionGUID as uniqueidentifier)

    SELECT ...

    -- Do other stuff (if CAST succeeds)

    It works fine as long as the string can be cast as a valid uniqueidentifier, but if the string is invalid, an error is generated (reassuringly!).

    <Server: Msg 8169, Level 16, State 2, Procedure up_wwwValidateSessionGUID, Line 16

    Syntax error converting from a character string to uniqueidentifier.>

    In this context I'ld be happy for the s.p. to terminate and return nothing after such a failure, but I'ld like to clear the error first. Even better would be to anticipate the error and exit.

    I could validate the uniqueidentifier string on the client side, or I could just clear the error when it is returned to the calling vb, but I suspect there is a cleaner way (?)

    As an aside, one reason why I prefer to maintain all the error handling logic in the s.p is that it's a security token being passed and I'ld prefer that the outcome is either success or failure with no explanatory information.

    Cheers

    Will

  • Internal to SQL the answer is no. You will need to build that logic into the application itself to check for an error return code and message. Then you decide based on that how to fix and resubmit in the application.

    "Don't roll your eyes at me. I will tape them in place." (Teacher on Boston Public)

  • In response to myself (inspiration strikes too late again!) ....

    I guess one way to validate a uniqueidentifier field is to test thus, but anyone know a cleaner more generic way (that might work for other datatypes etc.)

    IF @vcrGUID LIKE '

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [-]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [-]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [-]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [-]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    [A-Z,1-9][A-Z,1-9]

    '

    ...

  • Thanks Antares - I couldn't find any way to do it in the documentation, but without your reply I would have wasted plenty of time looking for it here there and everywhere -

    Cheers

    PS (didn't see your post before I wrote back to myself).

  • I have the same problem but I really need to anticipate the error in the S.P.

    This is the function I wrote based in planet115 self reply.

    IF EXISTS (SELECT *

    FROM sysobjects

    WHERE name = N'varchar36isuniqueidentifier')

    DROP FUNCTION varchar36isuniqueidentifier

    GO

    CREATE FUNCTION varchar36isuniqueidentifier

    (@cadena varchar(36))

    RETURNS bit

    AS

    BEGIN

    declare @error bit

    IF (@cadena LIKE '[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][-][A-F0-9][A-F0-9][A-F0-9][A-F0-9][-][A-F0-9][A-F0-9][A-F0-9][A-F0-9][-][A-F0-9][A-F0-9][A-F0-9][A-F0-9][-][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]')

    set @error = 1

    else

    set @error = 0

    RETURN @error

    END

    GO

    -- =============================================

    -- Example to execute function

    -- =============================================

    declare @GUID uniqueidentifier

    ,@cad varchar(36)

    set @GUID = newid()

    set @cad = CAST (@guid as varchar(36))

    select @GUID

    SELECT dbo.varchar36isuniqueidentifier('lo que sea')

    SELECT dbo.varchar36isuniqueidentifier(@cad)

    GO

    --Thanks planet115 for the inspiration.

  • This is a bit neater

    like replicate('[A-F0-9/-]',36)

    You needed to check for the - as well, or you could replace them with nothing.

    Simon Sabin

    Co-author of SQL Server 2000 XML Distilled

    http://www.amazon.co.uk/exec/obidos/ASIN/1904347088


    Simon Sabin
    SQL Server MVP

    http://sqlblogcasts.com/blogs/simons

  • Simon

    Thanks for the suggestion. However, unless I am missing something, I don't think I can use your extremely elegant solution for two reasons.

    The first is that it would 'allow' a string such as '----------------1---------------------'

    As you say, you could strip out any hyphens before testing, but then the next problem is that (to the best of my knowledge), the CAST function is very specific about what it will accept as a string representation of a uniqueidentifier.

    For example:

    SELECT CAST('5EAE1A80-4B4A-4FC8-A413-358F6D3E55CB' as uniqueidentifier)

    Works. Whereas (no hyphens)

    SELECT CAST('5EAE1A804B4A4FC8A413358F6D3E55CB' as uniqueidentifier)

    fails. So if you did remove the hyphens, you'ld have to put them back in, and by that time .... πŸ™‚

    However, thanks for introducing me to the replicate function which I'm sure will come in very handy.

    I must check out your book ... I've dabbled briefly with SQLXML for a data driven web application (I'm a bit of an XSL fan) and was really pleased with the performance and ease of use (once I got a handle on XML EXPLICIT queries), but my current knowledge is pretty superficial.

  • Ok, let’s put it together.

    IF EXISTS (SELECT *

    FROM sysobjects

    WHERE name = N'varchar36isuniqueidentifier')

    DROP FUNCTION varchar36isuniqueidentifier

    GO

    CREATE FUNCTION varchar36isuniqueidentifier

    (@cadena varchar(36))

    RETURNS bit

    AS

    BEGIN

    declare @error bit

    IF (@cadena LIKE replicate('[A-F0-9]',8)

              +'[-]'+replicate('[A-F0-9]',4)

              +'[-]'+replicate('[A-F0-9]',4)

              +'[-]'+replicate('[A-F0-9]',4)

              +'[-]'+replicate('[A-F0-9]',12))

    set @error = 1

    else

    set @error = 0

    RETURN @error

    END

    GO

    -- =============================================

    -- Example to execute function

    -- =============================================

    declare @GUID uniqueidentifier

    ,@cad varchar(36)

    set @GUID = newid()

    set @cad = CAST (@guid as varchar(36))

    select @GUID

    SELECT dbo.varchar36isuniqueidentifier('lo que sea')

    SELECT dbo.varchar36isuniqueidentifier(@cad)

    GO

    When I wrote the function it seemed to me that the solution was not very elegant, the function replicate did not came into my mind. Now I think that the solution is shorter but not neater. Anyway, looks better.

    Thanks planet115 for the inspiration and simonsabin for the appreciation.

  • πŸ™‚

    I'll be using that. Thanks everybody.

Viewing 9 posts - 1 through 8 (of 8 total)

You must be logged in to reply to this topic. Login to reply