J'utilise un CTE pour convertir les SSRS stockés ProC en BO stocké Proc, comme apparemment, je ne peux pas utiliser de tables Temps avec des objets métier.
J'ai cette requête:
;WITH cte1
AS
(
SELECT cv.issue
, cv.customfield
, CAST(STRINGVALUE AS NUMERIC) AS priority_num
--INTO #temp_priority_val
FROM proddb1.customfieldvalue cv WITH (NOLOCK)
INNER JOIN proddb1.customfield e WITH (NOLOCK)
ON cv.CUSTOMFIELD = e.id
AND e.cfname = 'Issue Priority')
,cte2
AS
(
SELECT a.ISSUE
, f.customvalue priority_num
--INTO #temp_priority
FROM cte1 a
INNER JOIN proddb1.customfieldoption f WITH (NOLOCK)
ON a.CUSTOMFIELD = f.CUSTOMFIELD
AND CAST(a.priority_num AS NUMERIC) = f.id)
SELECT * FROM cte2
Je continue à obtenir un Error converting data type nvarchar to numeric.
Erreur sur cette exécution. Le priority_num
colonne est une colonne Nvarparar qui est lancée dans le premier CTE. Lorsque j'exécute cela dans la déclaration originale, les tables TEMP fonctionnaient parfaitement. Ce doit être quelque chose avec la périmètre CTE?
Vous ne pouvez pas facilement contrôler l'ordre dans lequel SQL Server évaluera le contenu d'une colonne qui n'utilise pas le type de données correct (ou a une précision incompatible). Si vous essayez de lancer une colonne nvarchar à Numérique, même si vous avez des filtres qui devraient éliminer toutes les valeurs non numériques à partir de la considération, SQL Server peut toujours essayer ces premiers (voir plainte d'Erland à ce sujet sur UserVoice =). Il y a des cas où vous pouvez nidifier des CTES jusqu'à ce que les vaches rentrent à la maison, mais SQL Server poussera toujours cette évaluation à un endroit où vous ne l'attendez pas.
Tant que les agrégats et les fonctions du texte complet ne sont pas impliqués (voir ici et ici ), vous pouvez forcer cette évaluation avant la conversion à l'aide de CASE
expression. Voici une version simplifiée de votre requête sans CTES:
SELECT cfv.issue,
priority_num = CONVERT(NUMERIC(something, something),
CASE WHEN ISNUMERIC(cfo.customvalue)=1 THEN cfo.customvalue END)
FROM
proddb1.customfieldvalue AS cfv
INNER JOIN proddb1.customfield AS cf
ON cfv.CUSTOMFIELD = cf.id
INNER JOIN proddb1.customfieldoption AS cfo
ON cfv.CUSTOMFIELD = cfo.CUSTOMFIELD
AND CONVERT(NUMERIC(something, something),
CASE WHEN ISNUMERIC(cfo.customvalue)=1 THEN cfo.customvalue END) = cfo.id
WHERE cf.cfname = 'Issue Priority';
Vous devrez changer something, something
à la bonne précision/échelle (ou utilisez l'un des types INT
si vous n'avez pas besoin de décimales). Vous ne devez jamais déclarer des types de variation sans spécifier la longueur - Ce message de blog est à peu près Varchar, mais il s'applique vraiment à tous les types .
Si vous êtes sur SQL Server 2012 (il est toujours utile d'inclure des informations telles que la version de SQL Server que vous utilisez), vous pouvez simplifier ceci:
CONVERT(NUMERIC(something, something),
CASE WHEN ISNUMERIC(cfo.customvalue)=1 THEN cfo.customvalue END)
pour ça:
TRY_CONVERT(NUMERIC(something, something), cfo.customvalue)
Et cela sera effectivement plus fiable (puisque ISNUMERIC
peut retourner 1 et toujours échouer au temps de conversion pour des types spécifiques). J'ai blogué sur ce chemin de retour en 2002 .