将 SQL 替换为另一个 SQL 中的 where 子句的输出
output of replace SQL as a where clause in another SQL
对不起,垃圾标题。我可以用几句话说清楚我的问题。
我有一个 SQL,它给出了一个用竖线 (|) 分隔的 ID 列表。我想将这些 ID 作为 where 子句传递到另一个 sql 中。我可以使用 replace 将值从管道分隔转换为逗号分隔。
例如,ID 列表可能是
1|2|3|4
并使用替换我得到
1,2,3,4
select replace(value, '|', ',') from my_table;
如果我尝试将其传递到另一个 SQL,我想在其中查找这些 ID,我会收到错误消息
ORA-01722: invalid number
select * from my_table2 where id in (
select replace(value, '|', ',') from my_table);
现在我想我需要将输出转换为一个数字,但我不想将整个字符串转换为一个数字,只是在其中输入数值。
我怎样才能轻松做到这一点?
谢谢
这是一个复杂的表达式,但您可以使用 like
和 exists
:
select *
from my_table2
where exists (select 1
from my_table t1
where '|' || value || '|' like '%|' || id || '|%'
);
但是,my_table
中的数据结构存在根本问题。您不应该在字符串中存储任何内容的列表——尤其是 integer ids。正确的 SQL 方法是使用一个连接 table,每个 id 一行。 Oracle 还有其他数据结构,例如嵌套 tables,可以帮助解决这个问题。
我们按照以下方式进行。我们有一个函数可以拆分字符串和 returns table。代码是 TSQL,但我认为您可以轻松地将其更改为 ORACLE SQL
CREATE FUNCTION [dbo].[fStringToTable]
(
@List NVARCHAR(MAX) ,
@Splitter NVARCHAR(MAX)
)
RETURNS @ParsedList TABLE ( ID INT )
AS
BEGIN
DECLARE @ID NVARCHAR(MAX) ,
@Pos INT ,
@sqlstat NVARCHAR(MAX)
DECLARE @tbl TABLE ( ID INT )
SET @List = LTRIM(RTRIM(@List)) + @Splitter
SET @Pos = CHARINDEX(',', @List, 1)
IF REPLACE(@List, @Splitter, '') <> ''
BEGIN
WHILE @Pos > 0
BEGIN
SET @ID = LTRIM(RTRIM(LEFT(@List, @Pos - 1)))
IF @ID <> ''
BEGIN
INSERT INTO @tbl
( ID )
SELECT ( @ID )
END
SET @List = RIGHT(@List, LEN(@List) - @Pos)
SET @Pos = CHARINDEX(@Splitter, @List, 1)
END
END
INSERT INTO @ParsedList
SELECT ID
FROM @tbl
GROUP BY ID
RETURN
END
你的 select 将是
select * from my_table2 where id in (
SELECT ID FROM [dbo].[fStringToTable]('1,2', ','));
可能有两种情况:好的和坏的。
糟糕的情况是您的竖线分隔字符串存储在数据库中的某个位置,您无法将此设计更改为有意义的内容。如果是这样,您需要使用 like 运算符,如下所示:
select t2.*
from my_table2 t2, my_table t
where '|' || t1.value || '|' like '%|' || t2.id || '|%'
很好的例子是这个流水线不是持久的并且是由第一个 SQL 创建的。如果是这样,您应该只清除垃圾。删除流水线,将列表删除到一行中。制作内部 SQL return 所需的 ID 结果集,每行一个,并使用类似
的东西
select t2.*
from my_table2 t2
where t2.id in (select id from ...)
另一种情况是如果这个列表是从客户端传输的参数值。一些开发人员使用这种方法制作过滤器等。如果是这样,您应该更改客户端以传输更好的东西,比如 table 的数字。 SQL 会像
select t2.*
from my_table2 t2
where t2.id in (select column_value from table(cast :param as NumberTable))
对不起,垃圾标题。我可以用几句话说清楚我的问题。
我有一个 SQL,它给出了一个用竖线 (|) 分隔的 ID 列表。我想将这些 ID 作为 where 子句传递到另一个 sql 中。我可以使用 replace 将值从管道分隔转换为逗号分隔。
例如,ID 列表可能是
1|2|3|4
并使用替换我得到
1,2,3,4
select replace(value, '|', ',') from my_table;
如果我尝试将其传递到另一个 SQL,我想在其中查找这些 ID,我会收到错误消息
ORA-01722: invalid number
select * from my_table2 where id in (
select replace(value, '|', ',') from my_table);
现在我想我需要将输出转换为一个数字,但我不想将整个字符串转换为一个数字,只是在其中输入数值。
我怎样才能轻松做到这一点?
谢谢
这是一个复杂的表达式,但您可以使用 like
和 exists
:
select *
from my_table2
where exists (select 1
from my_table t1
where '|' || value || '|' like '%|' || id || '|%'
);
但是,my_table
中的数据结构存在根本问题。您不应该在字符串中存储任何内容的列表——尤其是 integer ids。正确的 SQL 方法是使用一个连接 table,每个 id 一行。 Oracle 还有其他数据结构,例如嵌套 tables,可以帮助解决这个问题。
我们按照以下方式进行。我们有一个函数可以拆分字符串和 returns table。代码是 TSQL,但我认为您可以轻松地将其更改为 ORACLE SQL
CREATE FUNCTION [dbo].[fStringToTable]
(
@List NVARCHAR(MAX) ,
@Splitter NVARCHAR(MAX)
)
RETURNS @ParsedList TABLE ( ID INT )
AS
BEGIN
DECLARE @ID NVARCHAR(MAX) ,
@Pos INT ,
@sqlstat NVARCHAR(MAX)
DECLARE @tbl TABLE ( ID INT )
SET @List = LTRIM(RTRIM(@List)) + @Splitter
SET @Pos = CHARINDEX(',', @List, 1)
IF REPLACE(@List, @Splitter, '') <> ''
BEGIN
WHILE @Pos > 0
BEGIN
SET @ID = LTRIM(RTRIM(LEFT(@List, @Pos - 1)))
IF @ID <> ''
BEGIN
INSERT INTO @tbl
( ID )
SELECT ( @ID )
END
SET @List = RIGHT(@List, LEN(@List) - @Pos)
SET @Pos = CHARINDEX(@Splitter, @List, 1)
END
END
INSERT INTO @ParsedList
SELECT ID
FROM @tbl
GROUP BY ID
RETURN
END
你的 select 将是
select * from my_table2 where id in (
SELECT ID FROM [dbo].[fStringToTable]('1,2', ','));
可能有两种情况:好的和坏的。
糟糕的情况是您的竖线分隔字符串存储在数据库中的某个位置,您无法将此设计更改为有意义的内容。如果是这样,您需要使用 like 运算符,如下所示:
select t2.*
from my_table2 t2, my_table t
where '|' || t1.value || '|' like '%|' || t2.id || '|%'
很好的例子是这个流水线不是持久的并且是由第一个 SQL 创建的。如果是这样,您应该只清除垃圾。删除流水线,将列表删除到一行中。制作内部 SQL return 所需的 ID 结果集,每行一个,并使用类似
的东西 select t2.*
from my_table2 t2
where t2.id in (select id from ...)
另一种情况是如果这个列表是从客户端传输的参数值。一些开发人员使用这种方法制作过滤器等。如果是这样,您应该更改客户端以传输更好的东西,比如 table 的数字。 SQL 会像
select t2.*
from my_table2 t2
where t2.id in (select column_value from table(cast :param as NumberTable))