Échec de la conversion SQL Server lors de l'utilisation de INSERT

J'ai une table existante pleine de données, qui peut être créée en utilisant

CREATE TABLE __EpisodeCost ( ActivityRecordID INT NOT NULL, ActCstID NVARCHAR(15), VolAmt FLOAT, ActCnt FLOAT, TotCst FLOAT, ResCstID NVARCHAR(50) ); 

Cela vient d'un stream que je n'ai aucun contrôle et je veux le convertir en ma propre version appelée EpisodeCost

 CREATE TABLE EpisodeCostCtp ( ActivityRecordID INT NOT NULL, ActCstID NVARCHAR(6), ResCstID NVARCHAR(7), ActCnt NVARCHAR(7), TotCst DECIMAL(18, 8) ); 

Maintenant, le problème que j'ai est avec les conversions. Je peux exécuter la requête

 SELECT ActivityRecordID, Cast(ActCstID AS NVARCHAR(6)), Cast(ResCstID AS NVARCHAR(7)), Cast(LTRIM(STR(ActCnt, 10)) AS NVARCHAR(7)), Cast(TotCst AS DECIMAL(18, 8)) FROM __EpisodeCostCtp; 

et il fournit des données, cependant, quand j'essaie d'exécuter

 INSERT INTO EpisodeCostCtp ( ActivityRecordID, ActCstID, ResCstID, ActCnt, TotCst ) SELECT ActivityRecordID, Cast(ActCstID AS NVARCHAR(6)), Cast(ResCstID AS NVARCHAR(7)), Cast(LTRIM(STR(ActCnt, 10)) AS NVARCHAR(7)), Cast(TotCst AS DECIMAL(18, 8)) FROM __EpisodeCostCtp; 

Je reçois

Msg 8115, niveau 16, état 8, ligne 102 erreur de dépassement arithmétique conversion numérique en type de données numérique. La déclaration a été résiliée.

Pourquoi puis-je SELECT utilisant les dissortingbutions pertinentes, mais ne peut pas INSERT dans la table cible?


Modifier. Je ne sais toujours pas ce qui se passe ici.

Selon les recommandations de Serg, j'ai tenté de localiser les loggings problématiques mais la requête

 SELECT ActivityRecordID, Cast(ActCstID AS NVARCHAR(6)), Cast(ResCstID AS NVARCHAR(7)), Cast(LTRIM(STR(ActCnt, 10)) AS NVARCHAR(7)), Cast(TotCst AS DECIMAL(18, 8)) FROM __EpisodeCostCtp WHERE TotCst > 9.999999999999999e9; 

renvoie zéro loggings. Passer à 9.999999999999999e8 fait, et la conversion / cast arrive sans erreur. J'ai scince changé la requête INSERT pour utiliser DECIMAL(36, 18) et maintenant l'insertion réussit, mais je ne suis toujours pas le plus sage. Clairement, je frappais une limite sur la dissortingbution, mais pourquoi SELECT fonctionne et INSERT échoue, je ne sais toujours pas.

comme c'est un problème de débordement que vous pourriez vouloir essayer

 SET ARITHABORT OFF 

à partir de https://docs.microsoft.com/en-us/sql/t-sql/statements/insert-transact-sql

Lorsqu'une instruction INSERT rencontre une erreur arithmétique (débordement, division par zéro ou erreur de domaine) survenant lors de l'évaluation de l'expression, le moteur de database traite ces erreurs comme si SET ARITHABORT est défini sur ON. Le lot est arrêté et un message d'erreur est renvoyé. Pendant l'évaluation d'expression lorsque SET ARITHABORT et SET ANSI_WARNINGS sont désactivés, si une instruction INSERT, DELETE ou UPDATE rencontre une erreur arithmétique, un dépassement, une division par zéro ou une erreur de domaine, SQL Server insère ou met à jour une valeur NULL. Si la colonne cible n'est pas NULL, l'action d'insertion ou de mise à jour échoue et l'user reçoit une erreur.

Je crois que dans votre colonne TotCst a des valeurs plus grandes que DECIMAL (18,8). Et la version 2008 de SQL SERVER obtient un résultat arrondi si le type de destination n'est pas assez grand. Mais il ne peut pas insert car la table n'accepte que les valeurs exactes.

Vous pouvez voir le résultat de mes deux requêtes sur SQL SERVER 2012:

  DECLARE @float FLOAT SET @float = 12345678911.12 SELECT CAST(@float AS decimal(18,8)) 

Résultat: une erreur de dépassement de capacité arithmétique s'est produite lors de la conversion de float en type de données numérique.

la même requête avec DECIMAL (19,8) à la place:

  DECLARE @float FLOAT SET @float = 12345678911.12 SELECT CAST(@float AS decimal(19,8)) 

Résultat: 12345678911.12000100

EDIT: vérifiez si votre outil de requête récupère tous les loggings. Sinon, peut-être que parmi les autres loggings il y a des valeurs plus grandes que DECIMAL (18.8)

Pour searchr les lignes qui provoquent le problème, essayez

 SELECT * FROM __EpisodeCostCtp WHERE TotCst > 9.999999999999999e9;