在instr()和IN中使用数组的SQLIte语句

时间:2019-01-30 00:18:54

标签: php sqlite

我在构造sqlite语句时遇到问题。我对instr()IN很熟悉,但是可以一起使用吗?我有一个包含多个子字符串的数组,我想查看一列是否包含其中的任何一个。

这是我没有运气试图完成的事情的一个例子

$array = array('-SVA[rev1]', '-KINGS[rev2]', '-TBS[rev3]');

$query2 = $db->query("SELECT * FROM BOT_Downloads WHERE instr( FileName, IN ('$array') ) AND SeriesTitle = 'The Simple Truth' ");

我知道使用LIKE '% %'而不是instr()是另一种方式,但是当将它与IN结合使用时,我同样会感到困惑

2 个答案:

答案 0 :(得分:1)

您的逻辑需要完全修改; IN是一个SQL语句,用于确定IN语句左侧参数的内容是否等于该语句括号中的任何文字逗号分隔值,并且不是INSTR函数的有效参数。当您尝试执行该语句时,应该从SQLite收到错误消息。

您当前的代码应产生一个类似于以下内容的SQL查询:

SELECT *
FROM BOT_Downloads
WHERE instr( FileName, IN ('-SVA[rev1],-KINGS[rev2],-TBS[rev3]') )
    AND SeriesTitle = 'The Simple Truth';

我保证这不是您想要的。您想构建一个看起来更像这样的语句:

SELECT *
FROM BOT_Downloads
WHERE (
    instr( FileName, '-SVA[rev1]') or
    instr( FileName, '-KINGS[rev2]') or
    instr( FileName, '-TBS[rev3]'))
    AND SeriesTitle = 'The Simple Truth’;

顺便说一句,PHP数组函数不会用单引号将数组元素引起来,因此您的代码将构建如下语句:

SELECT *
FROM BOT_Downloads
WHERE instr( FileName, IN ('-SVA[rev1],-KINGS[rev2],-TBS[rev3]'))
AND SeriesTitle = 'The Simple Truth’;

您可能正在拍摄更像这样的东西:

SELECT *
FROM BOT_Downloads
WHERE instr( FileName, IN ('-SVA[rev1]','-KINGS[rev2]','-TBS[rev3]'))
AND SeriesTitle = 'The Simple Truth’;

但是,由于IN子句不是Instr函数的有效参数,因此任何一种方法都是错误的。 IN子句要求每个字符串文字都有定界符,否则,它将由等号运算符查找括号中包含的一个字符串。默认情况下,PHP数组方法不包含那些定界符。

继续:

在继续前面的回答时,我使用以下SQL创建并填充了测试表:

BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS `BOT_Downloads` (
    `FileName`      TEXT,
    `SeriesTitle`   TEXT,
    `Note`  TEXT
);
INSERT INTO `BOT_Downloads` (FileName,SeriesTitle,Note) VALUES ('File-SVA[rev1].txt','The Simple Truth','matches filename and series title'),
 ('File-KINGS[rev2].txt','The Simple Truth','matches filename and series title'),
 ('File-TBS[rev3].txt','The Simple Truth','matches filename and series title'),
 ('File-WTH[rev1].txt','The Simple Truth','matches series title, doesn’t match filename'),
 ('File-KINGS[rev1].txt','The Simple Truth','matches series title, doesn’t match filename'),
 ('File-SVA[rev1].txt','War and Peace','matches filename, doesn’t match series title'),
 ('File-KINGS[rev2].txt','War and Peace','matches filename, doesn’t match series title'),
 ('File-TBS[rev3].txt','War and Peace','matches filename, doesn’t match series title'),
 ('File-WTH[rev1].txt','War and Peace','No matches'),
 ('File-KINGS[rev1].txt','War and Peace','No matches');
COMMIT;

然后我运行以下查询:

SELECT *
FROM BOT_Downloads
WHERE (
    instr( FileName, '-SVA[rev1]') or
    instr( FileName, '-KINGS[rev2]') or
    instr( FileName, '-TBS[rev3]'))
   AND SeriesTitle = 'The Simple Truth’;

并获得了您所要求的自然结果:

“ File-SVA [rev1] .txt”“简单的事实”“匹配文件名和系列标题” “ File-KINGS [rev2] .txt”“简单的真理”“匹配文件名和系列标题” “ File-TBS [rev3] .txt”“简单的真理”“匹配文件名和系列标题”

如果数组的元素是字符串,则使用PHP创建数组然后将其扩展为SQL语句的逻辑将无法正常工作,因为PHP不会自动将所需的字符串定界符添加到数组元素中。这就是为什么您必须在IN语句的查询中手动包括单个刻度线的原因。这将适用于整数,但对于IMO来说是一种不好的方法。由于您没有在要测试的每个单独的字符串元素周围放置字符串定界符,因此对于SQL引擎,您似乎正在查找文件名包含文字字符串'-SVA [rev1],-KINGS [rev2]的所有行。 ,-TBS [rev3]”不是您要查找的,这就是为什么即使没有语法错误也没有得到结果的原因。

答案 1 :(得分:0)

如果可以将数组项连接到此:

'-SVA[rev1],-KINGS[rev2],-TBS[rev3]'

然后:

SELECT * FROM BOT_Downloads 
WHERE 
  ',' || '-SVA[rev1],-KINGS[rev2],-TBS[rev3]' || ',' LIKE  '%,' || FileName || ',%' 
  AND 
  SeriesTitle = 'The Simple Truth'