TOKEN_GENERATOR ORACLE SQL 语句在 SQLite 中的等效项

What is equivalent of TOKEN_GENERATOR ORACLE SQL statement in SQLite

我正在 ORACLE 中处理一些 SQL 查询,它们具有以下结构:

WITH TOKEN_GENERATOR AS (
    SELECT REGEXP_SUBSTR(:token_0, '[^,]+', 1, LEVEL) token
    FROM DUAL
    CONNECT BY LEVEL <= length(:token_0) - length(REPLACE(:token_0, ',', '')) + 1
)

其中 token_0 具有逗号分隔的绑定值,例如1,2,3,4。此子句与 SELECT 语句结合使用,引用如下:

WITH TOKEN_GENERATOR AS (
    SELECT REGEXP_SUBSTR(:token_0, '[^,]+', 1, LEVEL) token
    FROM DUAL
    CONNECT BY LEVEL <= length(:token_0) - length(REPLACE(:token_0, ',', '')) + 1
)
SELECT ... FROM ... WHERE T.COL in (SELECT TOKEN FROM TOKEN_GENERATOR)

我的问题是如何在SQLite中做出类似的SQL声明?当然,我可以将 SELECT 语句的 in 部分替换为 T.COL in (?,?,?.....) 之类的内容,但是如果传递的值的数量非常大,例如以千计。 WITH TOKEN 语句允许 UNION 解决这个问题。 ORACLE 中的实际问题描述为 here.

SQLite 中没有等效的功能。

做你想做的事情的一种方法是使用递归 CTE,它会拆分逗号分隔列表和 return 每个值 1 行:

WITH TOKEN_GENERATOR AS (
  SELECT '' token, '1,2,3' || ',' value 
  UNION ALL
  SELECT SUBSTR(value, 1, INSTR(value, ',') - 1),
         SUBSTR(value, INSTR(value, ',') + 1)
  FROM TOKEN_GENERATOR       
  WHERE LENGTH(value) > 1
)
SELECT token 
FROM TOKEN_GENERATOR
WHERE token <> ''

参见demo
结果:

token
1
2
3

您可以像这样在查询中使用它:

WITH TOKEN_GENERATOR AS (
  SELECT '' token, :token_0 || ',' value 
  UNION ALL
  SELECT SUBSTR(value, 1, INSTR(value, ',') - 1),
         SUBSTR(value, INSTR(value, ',') + 1)
  FROM TOKEN_GENERATOR       
  WHERE LENGTH(value) > 1
)
SELECT ... FROM ... WHERE T.COL in (SELECT token FROM TOKEN_GENERATOR WHERE token <> '')

如果列表包含几个值,这会没问题,但对于数千个值,我认为递归 CTE 不是最佳选择,因为执行 CTE 后紧随其后的是运算符 IN 这对于数千行将再次表现不佳。

另一种方法是使用运算符 LIKE:

SELECT ... FROM ... 
WHERE ',' || :token_0 || ',' LIKE '%,' || T.COL || ',%'

您可以使用递归 WITH 子句:

WITH RECURSIVE tkn(value, e_pos) AS (
  SELECT 'a,b,c,d,e',
         INSTR('a,b,c,d,e', ',')
UNION ALL
  SELECT SUBSTR(value, e_pos + 1),
         INSTR( SUBSTR(value, e_pos + 1), ',' )
  FROM   tkn
  WHERE  e_pos > 0
)
SELECT CASE
       WHEN e_pos = 0
       THEN value
       ELSE SUBSTR( value, 1, e_pos - 1 )
       END AS VALUE
FROM   tkn;

输出:

VALUE
a
b
c
d
e

db<>fiddle here