SELECT TOP COALESCE和bigint

时间:2016-03-09 04:03:16

标签: sql sql-server

忽略以下sql查询的实用性

DECLARE @limit BIGINT

SELECT TOP (COALESCE(@limit, 9223372036854775807))
    *
FROM
    sometable

警告

  

为TOP或FETCH子句行计数参数提供的行数必须是整数。

为什么它不起作用,但以下工作?

SELECT TOP 9223372036854775807
    *
FROM
    sometable

COALESCE(@limit, 9223372036854775807)为空时,9223372036854775807确实是@limit

我知道将COALESCE更改为ISNULL有效,但我想知道原因。

3 个答案:

答案 0 :(得分:2)

https://technet.microsoft.com/en-us/library/aa223927%28v=sql.80%29.aspx

  

指定bigint常量

     

超出int支持范围的整数常量   数据类型继续被解释为数字,标度为0和   足以保持指定值的精度。例如,   常量3000000000被解释为数字。这些数字常量   可隐式转换为bigint,可以分配给bigint   列和变量:

DECLARE @limit bigint
SELECT SQL_VARIANT_PROPERTY(COALESCE(@limit, 9223372036854775807),'BaseType') 
SELECT SQL_VARIANT_PROPERTY(9223372036854775807, 'BaseType') BaseType

显示9223372036854775807为numeric,因此合并的返回值为数字。而

DECLARE @limit bigint
SELECT SQL_VARIANT_PROPERTY(ISNULL(@limit, 9223372036854775807),'BaseType') 

给出bigint。差异为ISNULL返回值具有第一个表达式的数据类型,但COALESCE返回值具有最高的数据类型。

SELECT TOP (cast(COALESCE(@limit, 9223372036854775807) as bigint))
    *
FROM
    tbl

应该有用。

答案 1 :(得分:1)

DECLARE
  @x AS VARCHAR(3) = NULL,
  @y AS VARCHAR(10) = '1234567890';

SELECT
  COALESCE(@x, @y) AS COALESCExy, COALESCE(@y, @x)
    AS COALESCEyx,
  ISNULL(@x, @y) AS ISNULLxy, ISNULL(@y, @x)
    AS ISNULLyx;

输出:

COALESCExy      COALESCEyx      ISNULLxy        ISNULLyx
----------      ----------      --------        ----------
1234567890      1234567890      123             1234567890

请注意,对于COALESCE,无论首先指定哪个输入,输出的类型都是VARCHAR(10) - 具有更高优先级的输出。但是,使用 ISNULL时,输出的类型由第一个输入决定。因此,当第一个输入是VARCHAR(3)数据类型(表达式别名为ISNULLxy)时,输出为VARCHAR(3)。结果,在输入@y中产生的返回值在三个字符后被截断。这意味着isnull不会改变类型,但是会合并。

答案 2 :(得分:1)

原来9223372036854775807是一个数字而不是bigint

来自https://technet.microsoft.com/en-us/library/aa223927(v=sql.80).aspx

  

超出int数据类型支持的范围的整数常量继续被解释为数字,标度为0,精度足以保存指定的值

所以我们需要明确地将它转换为bigint

DECLARE @limit BIGINT

SELECT TOP (COALESCE(@limit, CAST(9223372036854775807 AS BIGINT)))
    *
FROM
    sometable