Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL占位符在问题的位置,插入的字符串失败_Sql - Fatal编程技术网

SQL占位符在问题的位置,插入的字符串失败

SQL占位符在问题的位置,插入的字符串失败,sql,Sql,作为我工作的一部分,我需要编写SQL查询以连接到PI数据库。要生成查询,我需要传递一个标记数组(基本上是主键),但这些标记必须作为字符串插入 由于这将是一个模块化查询,并用于多个标记,因此将使用占位符 查询依赖于WHERE IN语句的使用,即占位符所在的位置,如下所示: SELECT SUM(value * 5/1000) as "Hourly Flow [kL]" FROM piarchive..pitotal WHERE tag IN (?) AND time betwee

作为我工作的一部分,我需要编写SQL查询以连接到PI数据库。要生成查询,我需要传递一个标记数组(基本上是主键),但这些标记必须作为字符串插入

由于这将是一个模块化查询,并用于多个标记,因此将使用占位符

查询依赖于WHERE IN语句的使用,即占位符所在的位置,如下所示:

SELECT SUM(value * 5/1000) as "Hourly Flow [kL]" 
  FROM piarchive..pitotal 
 WHERE tag IN (?) 
   AND time between ? and ? 
   AND timestep = '1d' 
   AND calcbasis = 'Eventweighted' 
   AND value <> ''
…这是有效的

如果我尝试将相同的标记添加到占位符中,查询将失败。如果我只添加1个标记,没有使用占位符的引号,那么查询就可以工作


为什么会这样?它周围有什么东西吗

当您尝试将所有数字放入占位符时,占位符将被视为单个字符串,而不是逗号分隔的项目列表。因此,除非您的表中恰好有一个值与该字符串完全匹配,否则它将永远不会工作


解决方案是为需要匹配三个项目(例如三个占位符)的每个项目使用占位符,或者不使用占位符,而是连接整个SQL字符串并执行。当然,由于SQL注入的可能性,不建议这样做。

我以前在我们的报告解决方案中遇到过这个问题,用户希望能够在独立的下拉控件中输入最多5个值。这些控件中填充了可能的值,空值表示不使用第一个控件不允许空值,因为您至少有一种可能

我们的查询将代码片段转换为您的情况:

WHERE tag IN (?,?,?,?,?)
然后,当我们设置占位符时,我们将下拉列表中的值分配给它们各自的占位符,但有一个限制条件:如果下拉列表包含NULL,我们将用第一个下拉列表的内容填充占位符

这样,如果您输入7,3,1,8,9,您将得到:

WHERE tag IN (7,3,1,8,9)
如果输入7,NULL,1,NULL,9,则会得到:

WHERE tag IN (7,7,1,7,9)
等等。我们使用的DBMS足够聪明,可以在执行语句之前将语句折叠为最有效的形式,因此这样做不会带来任何实际损失。您的里程可能会有所不同


这种混乱的一个问题是,您必须为in子句中可能的条目数设置一个上限,但在我们的情况下这不是问题。

我们询问了供应商,得到了这样的回答,这允许我们传递一组以逗号分隔的标记

select *
from pitotal
where tag IN (SELECT tag from pipoint WHERE INSTR(?, tag) <> 0) and time between 'y' and 't'
基本上是做一系列的字符串比较


希望这对其他人有用

什么数据库?动态IN子句需要使用动态SQL,或者使用函数将IN子句转换为要连接到的表。这是针对PI数据库的,来自OSIsoft。它不是真正的关系数据库,但OLEDB驱动程序允许使用普通数据库SQL@AlistairPitts:如果PI中没有原生的动态SQL支持,你可以用你正在使用的任何应用程序语言将查询构造成字符串。是的,这就是我害怕的。不幸的是,SQL是静态的,我无法在需要时动态构建它。标签的数量将不断变化,这就是我希望在where in中找到的
select *
from pitotal
where tag IN (SELECT tag from pipoint WHERE INSTR(?, tag) <> 0) and time between 'y' and 't'