将 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);

现在我想我需要将输出转换为一个数字,但我不想将整个字符串转换为一个数字,只是在其中输入数值。

我怎样才能轻松做到这一点?

谢谢

这是一个复杂的表达式,但您可以使用 likeexists:

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

看到这个http://www.adp-gmbh.ch/ora/plsql/coll/return_table.html

可能有两种情况:好的和坏的。

糟糕的情况是您的竖线分隔字符串存储在数据库中的某个位置,您无法将此设计更改为有意义的内容。如果是这样,您需要使用 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))