输出替换SQL作为另一个SQL中的where子句

时间:2015-01-20 11:46:29

标签: sql oracle casting

抱歉垃圾标题。我可以用几句话清楚地表达我的问题。

我有一个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);

现在我假设我需要将输出强制转换为数字,但我不想将整个字符串转换为数字,而只是将数字值转换为数字值。

我怎样才能轻松完成这项工作?

由于

3 个答案:

答案 0 :(得分:2)

这是一个复杂的表达方式,但您可以使用likeexists执行此操作:

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', ','));

请参阅此http://www.adp-gmbh.ch/ora/plsql/coll/return_table.html