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
我正在 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