web-dev-qa-db-fra.com

serveur SQL - vérifie si la distribution est possible

J'ai le code suivant pour convertir nvarchar en entier:

     cast(@value as int)

Cependant, je n’ai aucun contrôle sur le paramètre @value, le code peut donc échouer. Est-il possible de vérifier si un casting est possible avant de le faire?

21
Bruce

Eh bien, dans SQL Server 2012, vous pouvez utiliser le nouveau TRY_CAST () , mais avec SQL Server 2008, vous devriez pouvoir utiliser ISNUMERIC () , puis inclure la gestion des valeurs qui ne le transmettent pas. tester.

24
Matt

J'ai récemment répondu à une question à ce sujet et utiliser ISNUMERIC pour CAST en INT ne fonctionnera pas tout seul. La raison étant ISNUMERIC renvoie true pour les nombres non entiers (1.5) par exemple. 

Voici une réponse récente sur le sujet: 

https://stackoverflow.com/a/14692165/1073631

Envisagez d'ajouter une vérification supplémentaire à l'aide de CHARINDEX avec ISNUMERIC, ou ce que je préfère, utilisez une expression régulière pour valider les données.

Et voici un Fiddle démontrant le problème lié à l'utilisation d'ISNUMERIC seul. Et le Fiddle qui utilise une expression régulière à la place qui fonctionne.

DECLARE @Test nvarchar(10)
SET @Test = '1.5'
--Works
SELECT CASE WHEN @Test NOT LIKE '%[^0-9]%' THEN CAST(@Test as int) ELSE 0 END 
-- Produces Error
SELECT CASE WHEN ISNUMERIC(@Test) = 1 THEN CAST(@Test as int) ELSE 0 END 

Bonne chance.

11
sgeddes

J'utilise généralement ce qui suit, il semble couvrir toutes les situations.

SELECT CASE WHEN 1 = ISNUMERIC(@value + '.0') THEN CAST(@value as int) ELSE 0 END

Il profite du fait que "ISNUMERIC" ne permettra pas deux périodes. Le "TRY_CAST" dans SQL Server 2012+ est cependant une bien meilleure solution.

7
Michael Erickson

Peut-être que nous pouvons faire quelque chose comme ça:

declare @value as nvarchar(10) = 'A';

begin try
    select cast(@value as int);
end try
begin catch
-- do something
end catch
1
Anoop Verma

Le test approprié est:

select (case when isnumeric(val) = 1 and val not like '%e%' and val not like '%.%'
             then cast(val as int)
        end)

La fonction isnumeric() renvoie 1 pour tout ce qui ressemble à un float, vous devez donc faire attention.

Vous pouvez également utiliser ce que je considère être une particularité de SQL Server. Vous pouvez convertir la valeur flottante 1.23 en un entier, mais vous ne pouvez pas convertir la valeur de chaîne. Donc, ce qui suit fonctionne aussi:

select (case when isnumeric(val) = 1
             then cast(cast(val as float) as int)
        end)
1
Gordon Linoff

Utilisez une procédure avec un bloc TRY CATCH pour supprimer les erreurs

c'est à dire.

CREATE PROCEDURE p_try_cast
 @type nvarchar(MAX),
 @value nvarchar(MAX)
AS
BEGIN

    BEGIN TRY
        DECLARE @sql        varchar(MAX)
        DECLARE @out_table  TABLE(value varchar(MAX))

        SET @sql = 'SELECT  CONVERT(varchar(max), CAST(''' + @value + ''' AS ' + @type + '))'

        INSERT  @out_table
        EXECUTE (@sql)

        IF EXISTS ( SELECT 1 FROM @out_table WHERE value = @value)
            RETURN 1

        RETURN 0
    END TRY
    BEGIN CATCH
        RETURN 0
    END CATCH

END

GO

Maintenant, vous pouvez appeler cela avec la chaîne passée et le type souhaité et le proc retourne 1 pour succès et 0 pour échec

DECLARE @ret int

-- This returns 0 - Fail
EXEC @ret = p_try_cast 'integer', '1.5'

-- This returns 1 - Success
EXEC @ret = p_try_cast 'integer', '1.5'

-- This returns 0 - Fail
EXEC @ret = p_try_cast 'char(4)', 'HELLO'

-- This returns 1 - Success
EXEC @ret = p_try_cast 'char(4)', 'HELL'
0
cmdr_putin