Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

erreur lors de la conversion de varchar en float

Cela signifie que vous avez au moins une ligne dans la table qui ne peut pas être convertie en float . Faire le CASE est sûr, mais combiner le CTE et ajouter une clause WHERE tombe dans une erreur courante des programmeurs lors de l'écriture de T-SQL :cet ordre de déclaration implique un ordre d'exécution . Les programmeurs sont habitués au style procédural impératif des langages de type C et ne comprennent pas la nature déclarative basée sur les ensembles de SQL. J'ai déjà écrit sur ce problème et donné des exemples où l'erreur provoque des erreurs :

Une fois que vous avez posté votre code complet, nous pouvons voir exactement où vous avez commis l'erreur dans votre cas et supposé un certain ordre d'exécution.

après mise à jour

OK, je dois donc administrer que dans votre cas le code est correct dans l'ordre d'exécution, le result la colonne ne peut pas être projetée sans d'abord évaluer le CASE . Si le CASE avait été dans une clause WHERE, les choses auraient été différentes.

Votre problème est différent :ISNUMERIC . Cette fonction a une compréhension très généreuse de ce que NUMERIC signifie et a mordu de nombreux développeurs avant. A savoir, il accepte les valeurs que CAST et CONVERT rejetteront. Comme celles contenant une virgule :

declare @n varchar(8000) = '1,000';
select isnumeric(@n);
select cast(@n as float);
select case when isnumeric(@n)=1 then cast(@n as float) else null end;

Vous avez donc des valeurs qui passent le ISNUMERIC test mais ne parvient pas à convertir. Juste un avertissement, plus vous approfondirez cette approche, plus vous trouverez de portes fermées. Il n'y a tout simplement pas de moyen sûr de faire le casting dont vous avez besoin côté serveur. Idéalement, corrigez le modèle de données (faites du champ un flottant s'il stocke des flottants). En dehors de cela, triez les données et supprimez toutes les valeurs qui ne sont pas un flotteur approprié, et corrigez le front-end/application pour ne plus en introduire de nouvelles, puis ajoutez une contrainte qui déclenchera l'erreur si de nouvelles mauvaises valeurs apparaissent. Vous ne pourrez pas résoudre cela dans une requête, cette route est jonchée de corps.

Avec la prochaine version de SQL Server, vous aurez une nouvelle fonction, TRY_CONVERT , cela résoudrait votre problème.