简体   繁体   English

SQL生成的联接与VARCHAR小数转换

[英]SQL Generated Joins with VARCHAR Casting of Decimals

I have a SQL Generator in C# which allows users to pass in parameters which specify a table to join to, and which keys to join on. 我在C#中有一个SQL生成器,它允许用户传递参数,这些参数指定要联接的表以及要联接的键。

Given the flexibility, and the fact that SQL sometimes didn't cast the field appropriately, the query ended up like so: 考虑到灵活性,以及​​SQL有时无法正确转换字段的事实,查询最终如下所示:

SELECT * FROM [SourceTable] AS [src]
INNER JOIN [JoinTable] [join1] ON CAST([join1].[someField] AS VARCHAR(5000)) = CAST([src].[otherFIeld] AS VARCHAR(5000))
WHERE [blah] = 'blah'

This has worked for quite some time, until it was required that the someField column on JoinTable be changed from a float to a decimal. 这已经工作了很长一段时间,直到需要将someField上的someField列从浮点数更改为小数点JoinTable So now instead of '1234' = '1234' working as expected, we get '1234.00000000000' = '1234' which of course fails. 因此,现在不是'1234' = '1234'正常工作,而是得到'1234.00000000000' = '1234' ,这当然会失败。

The biggest kink which is stopping me from a quick fix is that that fields don't have to be numeric. 使我无法快速解决问题的最大难题是,字段不必为数字。 They could very well pass in fields that join on lastName or something, and so I can't just TRY_CONVERT to float or something. 他们可以很好地传递连接在lastName或其他名称上的字段,因此我不能只是TRY_CONVERT来浮动或其他名称。

The second kink is that this is a join, not just a select, so I don't know the repercussions of putting a bunch of logic in a join, or if that's even possible. 第二个纠结是这是一个联接,而不仅仅是一个选择,所以我不知道在联接中加入一堆逻辑的影响,或者甚至是可能的。 Otherwise I wonder if I could do an IsNumeric type check and, if true, tryconvert to float, then cast to varchar, otherwise just cast to varchar? 否则我想知道是否可以进行IsNumeric类型检查,如果为true,请尝试转换为float,然后转换为varchar,否则仅转换为varchar?

We are using SQL Servers between 2014 and 2016 我们在2014年至2016年之间使用SQL Server

SELECT * FROM [SourceTable] AS [src] 
    INNER JOIN [JoinTable] [join1] 
    ON (CASE WHEN isnumeric('join1].[someField]')=1 
        then  CAST(CAST([join1].[someField] AS FLOAT) AS VARCHAR(50))
         ELSE 
             CAST([join1].[someField] AS varchar(50)) end) = 
      (CASE WHEN isnumeric([src].[otherFIeld])=1 then  CAST(CAST([src].
      [otherFIeld] AS FLOAT) AS VARCHAR(50)) 
       ELSE  CAST([src].[otherFIeld] AS varchar(50)) end)
      WHERE [blah] = 'blah'

Otherwise I wonder if I could do an IsNumeric type check and, if true , tryconvert to float, then cast to varchar, otherwise just cast to varchar? 否则我想知道是否可以进行IsNumeric类型检查,如果为true,则尝试转换为float,然后转换为varchar,否则仅转换为varchar?

Yes you have to do it exactly like this.cast both side of join to same data type. 是的,您必须像这样完全做到这一点。将连接的两面都铸造为相同的数据类型。

SELECT * FROM [SourceTable] AS [src]
INNER JOIN [JoinTable] [join1] ON CAST([join1].[someField] AS VARCHAR(5000)) = CAST([src].[otherFIeld] AS VARCHAR(5000))
WHERE [blah] = 'blah' and ISNUMERIC([join1].[someField])=0 and ISNUMERIC([src].[otherFIeld])=0
union ALL
SELECT * FROM [SourceTable] AS [src]
INNER JOIN [JoinTable] [join1] ON CAST([join1].[someField] AS float) = CAST([src].[otherFIeld] AS float)
WHERE [blah] = 'blah' and ISNUMERIC([join1].[someField])=1 and ISNUMERIC([src].[otherFIeld])=1

declare @i decimal(10,4)=1234
declare @ii varchar(400)='1234'
--this won't work
select cast(@i as varchar(400)),@ii
-- this will work
select cast(@i as float),@ii

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM