【问题标题】:Use a variable in SQL Where clause that contains commas在 SQL Where 子句中使用包含逗号的变量
【发布时间】:2017-07-25 22:11:55
【问题描述】:

我在 SQL Server 2008 中有一个表。该表有一个名为 CC_TERMID 的字段,它是一个数字字段。我在 Oracle 服务器上有数据,我想在其中找到我们所在日期的当前 TermID,并且我想将其用作我的 SQL 表的变量。我很确定我的错误在于数据类型不匹配,但我不知道如何存储变量的数据。

这是我创建的变量,我使用 openquery 从 Oracle 中提取我想要的数据:

    DECLARE @TERMS nvarchar(50)
    SET @TERMS = (SELECT * FROM OPENQUERY(POWERSCHOOL,
    '
    SELECT TO_NUMBER(LISTAGG(ID, '','') WITHIN GROUP (ORDER BY SCHOOLID))
    FROM TERMS
    WHERE SYSDATE + (SELECT FIRSTDAY - SYSDATE
                     FROM TERMS
                     WHERE ISYEARREC = 1 AND YEARID = (SELECT MAX(SUBSTR(TERMID, 1,2))
                                                       FROM CC) AND SCHOOLID = 51) BETWEEN FIRSTDAY AND LASTDAY AND SCHOOLID = 51
   '))

这会返回像 2700,2701,2703,2704 这样的数据

现在我想在针对我的 SQL 表的查询中使用该变量,如下所示:

    SELECT TCH_EMAIL_ADDR, TCH_LAST_NAME, TCH_FIRST_NAME, CC_TERMID
    FROM ZPS_CCRAW
    WHERE CC_TERMID IN (@TERMS)

当然我得到错误:“将数据类型 nvarchar 转换为数字时出错”。我曾尝试将 CC_TERMID 转换为这样的 nvarchar:

    SELECT TCH_EMAIL_ADDR, TCH_LAST_NAME, TCH_FIRST_NAME, CC_TERMID
    FROM ZPS_CCRAW
    WHERE CAST(CC_TERMID AS NVARCHAR(50)) IN (@TERMS)

但我没有返回任何结果。如果我删除 @TERMS 并输入 2700,2701,2703,2704,那么我将得到按预期返回的数据。

在撰写陈述方面,我远非专家。我知道足以让我陷入这样的麻烦,但还不足以知道如何摆脱它。谁能帮我实现我正在寻找的东西?

【问题讨论】:

  • 为什么要使用变量?只需将您的查询输入in
  • Ilya Bursov - 我遇到的问题是 TermID 会根据日期发生变化。所以在这种情况下,第 1 季度将是 termID 的 2700,2701,2703,2706。当即将在 10 月底到来的第 2 季度时,我将需要 ID 的 2700,2701,2703,2707。每个季度将有一组不同的 ID。明年到来时,现在一切都变为 2800 年。我正在寻找一套它并忘记它的脚本,所以我不必总是手动调整代码。
  • 你的评论与我的问题有什么关系?
  • 对不起,Ilya Bursov,我看错了你的问题。你也对。我本可以将我的查询放入我的 in 语句中。这是我全神贯注地走这条路的项目之一,以至于我再也看不到其他任何东西了。
  • @rockman20 这里有经验丰富的 PowerSchool 人员 - 您可以从 TERMS 表中加入以获得您想要的术语,而不是您当前更改术语的策略。如果您对此感兴趣,您可以在我的 github 个人资料中找到我的联系信息,我们可以离线交谈

标签: sql-server sql-server-2008 openquery


【解决方案1】:

请您原谅我,我不擅长使用 Oracle,因此我对您的子查询所做的更改可能不太奏效。但基本上这个想法是,不要序列化列表。将其保留为设置数据即可。

  DECLARE @TERMS table (Id int)

  insert into @TERMS (Id)
  SELECT ID FROM OPENQUERY
  (
      POWERSCHOOL,
      'SELECT DISTINCT ID 
       FROM TERMS
       WHERE SYSDATE + (SELECT FIRSTDAY - SYSDATE
                        FROM TERMS
                        WHERE ISYEARREC = 1 AND YEARID = (SELECT MAX(SUBSTR(TERMID, 1,2))
                                                          FROM CC) AND SCHOOLID = 51) BETWEEN FIRSTDAY AND LASTDAY AND SCHOOLID = 51'
  )

然后将您的后续查询更改为如下内容:

 SELECT TCH_EMAIL_ADDR, TCH_LAST_NAME, TCH_FIRST_NAME, CC_TERMID
 FROM ZPS_CCRAW
 WHERE CC_TERMID IN (select Id @TERMS)

 SELECT TCH_EMAIL_ADDR, TCH_LAST_NAME, TCH_FIRST_NAME, CC_TERMID
 FROM ZPS_CCRAW a
 INNER JOIN @TERMS b
      on a.CC_TERMID = b.Id

注意,如果您愿意,您可以直接从 OPENQUERY 执行相同操作,而不是将它们转储到表变量中。

基本上发生的事情是您有一个看起来像...的表

... CC_TERMID
... 2700
... 2701
... 2703
... 2704 

...而您目前正在说“给我 CC_TERMID 等于字符串文字 "2700,2701,2703,2704" 的所有行

【讨论】:

  • 我的回答与 SQL Server 有关。他的远程查询的内容是用 PL/SQL (AKA Oracle) 编写的,正如他在文章的第二行中提到的那样。那是我不知道语法的部分。但是,我认为我已经说得很清楚了。至于@... 的东西,都是变量声明,OP 自己也有。
  • 谢谢 Xedni!我没有意识到我可以将表声明为变量。我唯一需要更改的是 (select Id @TERMS) 到 (select id FROM @TERMS) 否则这是一个完美的答案。我也很感激我了解到我可以将表声明为变量。
  • 很高兴我能帮上忙。
【解决方案2】:

您的 Oracle 查询没问题。这是 SQL Server 解释语句的方式。自从我使用 SQL Server 以来已经有一段时间了,但我认为您不能以这种方式使用变量。我会使用动态查询,因此 @terms 将被解释为值列表而不是字符串。

【讨论】:

  • 在 DSQL 中这样做的主要问题是它不是注入证明。
  • 注入的风险很小,因为您的变量是从选择语句而不是用户界面字段创建的。 select 语句返回一个难以注入的数字列表。
猜你喜欢
  • 1970-01-01
  • 2021-08-30
  • 2012-12-25
  • 2020-04-16
  • 2015-10-18
  • 2023-01-06
  • 2014-02-16
  • 2020-12-09
  • 1970-01-01
相关资源
最近更新 更多