抱歉垃圾标题。我可以用几句话清楚地表达我的问题。
我有一个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);
现在我假设我需要将输出强制转换为数字,但我不想将整个字符串转换为数字,而只是将数字值转换为数字值。
我怎样才能轻松完成这项工作?
由于
答案 0 :(得分:2)
这是一个复杂的表达方式,但您可以使用like
和exists
执行此操作:
select *
from my_table2
where exists (select 1
from my_table t1
where '|' || value || '|' like '%|' || id || '|%'
);
但是,my_table
中的数据结构存在根本问题。您不应该在字符串中存储任何内容的列表 - 尤其是整数 ID。正确的SQL方法是使用联结表,每个id一行。 Oracle有其他数据结构,例如嵌套表,这可以帮助解决这个问题。
答案 1 :(得分:1)
可能有两种情况:好的和坏的。
错误的情况是您的管道分隔字符串存储在数据库中的某个位置,您无法将此设计更改为有意义的内容。如果是这样,你需要使用like运算符,如下所示:
select t2.*
from my_table2 t2, my_table t
where '|' || t1.value || '|' like '%|' || t2.id || '|%'
好的情况是这种流水线操作不是持久性的,而是由第一个SQL创建的。如果是这样,你应该删除垃圾。删除管道,删除列表到一行。使内部SQL返回所需ID的结果集,每行一个,并使用类似
的内容 select t2.*
from my_table2 t2
where t2.id in (select id from ...)
其他情况是该列表是从客户端传输的参数值。一些开发人员使用这种方法来制作过滤器等。如果是这样,你应该更改客户端以更好地传输更好的东西,比如数字表。 SQL就像
select t2.*
from my_table2 t2
where t2.id in (select column_value from table(cast :param as NumberTable))
答案 2 :(得分:-1)
我们按以下方式进行。我们有一个函数可以拆分字符串并返回表。代码是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 * from my_table2 where id in (
SELECT ID FROM [dbo].[fStringToTable]('1,2', ','));