AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 108131
Accepted
Bogdan Bogdanov
Bogdan Bogdanov
Asked: 2015-07-27 03:32:09 +0800 CST2015-07-27 03:32:09 +0800 CST 2015-07-27 03:32:09 +0800 CST

TSQL 函数中的奇怪行为(具有 int 变量或 NULL 的参数表现不同)?

  • 772

我今天在使用 TSQL 函数时遇到了一个非常奇怪的问题。

该函数有几个参数(int 和 bit)。其中一个 (int) 被设置为 NULL 值。

在 params 函数中调用带有 NULL 的函数时返回 ERROR(错误是正常的,因为我尝试转换'%%'为int值)。当使用参数 @p1 调用该函数时,NULL该函数正在工作。

有人可以向我解释为什么它会这样吗?

我们正在使用:

Microsoft SQL Server 2012 (SP1) - 11.0.3000.0 (X64) 
    Oct 19 2012 13:38:57 
    Copyright (c) Microsoft Corporation
    Business Intelligence Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)

我的代码是: 导致错误的代码:

((@p IS NOT NULL) AND (CONS.IDp = @p)) OR
((@p IS NULL) AND (UFCFD.IDUser IS NOT NULL) AND
 (CONS.IDp = CAST(UFCFD.Value1 AS INT))

备注:我编辑“导致错误”部分是因为我的同事进行了保护检查。我删除了那部分以显示函数的原始状态(来源是:(CONS.IDp = CASE WHEN ISNUMERIC(UFCFD.Value1) = 1 THEN CAST(UFCFD.Value1 AS INT) ELSE NULL END))

导致错误的调用:

SELECT * FROM dbo.myFunc(NULL); 

有效的电话:

DECLARE @p INT = NULL;
SELECT * FROM dbo.myFunc(@p); 

PS 如果问题不清楚,请通过评论告诉我。

编辑2:

这是函数的全文:

CREATE FUNCTION dbo.myFunc
(   
    @IDUser INT, 
    @p INT,
    @IDGrid INT,
    @IsWithLead BIT,
    @IDLeadValueResource INT,
    @IDLanguage INT,
    @IsAllPresent BIT,
    @IDAllValueResource INT
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT
        -99999999 AS ID,
        dbo.funs_GetResourceText(@IDLanguage,@IDAllValueResource) AS [Text],
        -99999999 AS Sort
    WHERE (@IsAllPresent = 1)

    UNION ALL

    SELECT
        0 AS ID,
        dbo.funs_GetResourceText(@IDLanguage,@IDLeadValueResource) AS [Text],
        0 AS Sort
    WHERE (@IsWithLead = 1)

    UNION ALL

    SELECT 
        CONS.IDConsumerType AS ID,
        CASE
            WHEN @IDLanguage = 40001 THEN CONS.ConsumerType_Name_en  
            WHEN @IDLanguage = 40002 THEN CONS.ConsumerType_Name_it 
            WHEN @IDLanguage = 40003 THEN CONS.ConsumerType_Name_de 
            WHEN @IDLanguage = 40004 THEN CONS.ConsumerType_Name_fr 
            ELSE CONS.ConsumerType_Name_en END AS [Text],
        ROW_NUMBER() OVER(ORDER BY CONS.SegmentOrder ASC) AS Sort
    FROM 
        dbo.V_ConsumerTypes AS CONS
        LEFT JOIN dbo.Grids GRD ON (GRD.ID = @IDGrid)
        LEFT JOIN dbo.CONFieldCollection_FieldDefinition FCFD ON
            (FCFD.IDFieldCollection = GRD.IDGridFieldCollection) AND
            (FCFD.FieldName LIKE '%IDp%')
        LEFT JOIN dbo.CONUser_FieldCollection_FieldDefinition UFCFD ON
            (UFCFD.IDFieldCollection = GRD.IDGridFieldCollection) AND
            (UFCFD.IDUser = @IDUser) AND
            (UFCFD.IDFieldCollections_FieldDefinitions = FCFD.ID) 
    WHERE
        ((@p IS NOT NULL) AND (CONS.IDp = @p)) OR
        ((@p IS NULL) AND (UFCFD.IDUser IS NOT NULL) AND
         (CONS.IDp = CAST(UFCFD.Value1 AS INT))
)

有效的电话是:

DECLARE @IDUser INT = -100;
DECLARE @p INT = NULL;
DECLARE @IDGrid INT = 17;
DECLARE @IsWithLead BIT = 0;
DECLARE @IDLeadValueResource INT = 0;
DECLARE @IDLanguage INT = 40002;
DECLARE @IsAllPresent BIT = 1
DECLARE @IDAllValueResource INT = -177;

DECLARE @dt DATETIME = GetDate();
SELECT * FROM dbo.fun_ClROME_MdFillComboConsumerTypes(@IDUser, @p, @IDGrid, @IsWithLead, @IDLeadValueResource,
    @IDLanguage, @IsAllPresent, @IDAllValueResource)
ORDER BY Sort

如果我们使用NULL而不是@p然后我收到错误,因为我尝试转换'%%'为int- 这是正确的。

问题是显然函数的行为不同,这是一个大问题。

t-sql sql-server-2012
  • 1 1 个回答
  • 1044 Views

1 个回答

  • Voted
  1. Best Answer
    Aaron Bertrand
    2015-07-27T06:51:44+08:002015-07-27T06:51:44+08:00

    我认为您正在尝试解决错误的问题。正如我在上面所建议的那样,我认为您得到不同的结果仅仅是因为您目前有不同的计划(一个用于文字,一个用于变量)。您当前获得的导致错误的计划是在过滤掉行之前尝试强制转换,但是如果重新编译当前“工作正常”的计划,这两种方法都可能导致错误。

    您应该做的是使用表达式来确保实际上只尝试转换可以转换CASE为 an 的数值。INT你需要明确地控制它,因为你不能总是依赖 SQL Server 在尝试计算之前过滤行。

    在 2012 年及以后,您可以简单地替换它:

    (CONS.IDp = CAST(UFCFD.Value1 AS INT))
    

    有了这个:

    (CONS.IDp = TRY_CONVERT(INT, UFCFD.Value1))
    

    如果您还必须支持旧版本,您可以这样做(因为我们知道ISNUMERIC()这还不够):

    (CONS.IDp = CASE 
      WHEN UFCFD.Value1 NOT LIKE '%[^0-9]%' 
      AND 
      (
        LEN(UFCFD.Value1 < 11 
        OR
        (
          LEN(UFCFD.Value1) = 11 
          AND LEFT(UFCFD.Value1,1) IN ('0','1','2')
        )
      ) THEN CONVERT(INT, UFCFD.Value1) END)
    

    表达式对于CASE强制 SQL Server 以特定顺序计算表达式非常可靠,但请注意也有例外。

    • 4

相关问题

  • 如何判断 SQL Server 数据库是否仍在使用?

  • 为什么 Denali 序列应该比标识列表现更好?

  • 实施 PIVOT 查询

  • SQL Server 不应该支持范围吗?

  • 什么是 SQL Server“德纳利”?什么是新的?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve