【问题标题】:Select all rows which occure in list of 2927 id's选择 2927 id 列表中出现的所有行
【发布时间】:2016-11-02 06:13:12
【问题描述】:

我有一个 2927 id 的列表。我想获取该列表中所有 id 的行。我怎样才能做到这一点?它是一个逗号分隔的 id 列表。由于限制为 1000,因此 in 语句不起作用。我尝试过类似 Loop through pre defined values 的解决方案,但它没有达到我的预期。

我正在使用 toad,我希望查看数据网格中的行(多行、多列)。

提前致谢!

id 列表的外观如下:

67,122,173,256,284,285,288,289,291,294,296,298,301,320,346,359,366,425,428,454,528,573,576,584,593,654,654,694,722,838,1833,1976,1979,1979,2002,2004,2005,2045,2083,2109,2114,2126,2126,2157,2204,2204,2211,2212,2332,2576,...

当未达到 1000 的限制时,语句将如何:

Select * from tablename where tablename.id in (67,122,173,256,284,285,288,289,291,294,296,298,301,320,346,359,366,425,428,454,528,573,576,584,593,654,654,694,722,838,1833,1976,1979,1979,2002,2004,2005,2045,2083,2109,2114,2126,2126,2157,2204,2204,2211,2212,2332,2576);

【问题讨论】:

  • 将所有这些值放在一个临时表中。
  • 这可以解决问题:blogs.oracle.com/aramamoo/entry/…
  • 你为什么要使用这样的ID?如果超过 1000 个,您应该考虑将它们放在一个表中。
  • @neurotic-d 这给了我一个错误'string literal to long'
  • @PirateX 这是一个生产数据库,我可能不会更改。

标签: sql oracle toad


【解决方案1】:

这是另一种处理方法,即使用公用表表达式 (CTE) 将 ID 转换为逻辑表,然后像往常一样加入。这样想可能更容易理解它:

-- Build the list of IDs.
with data(str) as (
    select '67,122,173,256,284,285,288,289,291,294,296,298,301,320,346,359
     ,366,425,428,454,528,573,576,584,593,654,654,694,722,838,1833,1976,1979,1979,2002
     ,2004,2005,2045,2083,2109,2114,2126,2126,2157,2204,2204,2211,2212,2332,2576' 
    from dual
),
-- Turn the list into a table using the comma as the delimiter. Think of it
-- like a temp table in memory.
id_list(id) as (
  select regexp_substr(str, '(.*?)(,|$)', 1, level, NULL, 1)
  from data
  connect by level <= regexp_count(str, ',') + 1
)
-- Select data from the main table, joining to the id_list "temp" table where
-- the ID matches.
select tablename.*
from tablename, id_list
where tablename.id = id_list.id;

【讨论】:

    【解决方案2】:
    • 缓慢、丑陋但有效的解决方案:将字符串拆分为 id 并使用游标获取行 或
    • 根据字符串生成一个动态选择查询:'select * from tbl where id = 1 or id = 2 or ...' 并执行它,不会再快但会工作。

    【讨论】:

      【解决方案3】:

      不用于生产:

      with list as (
          select to_number(regexp_substr('67,122,173,256,284,285,288,289,291,294,296,298,301,320,346,359
           ,366,425,428,454,528,573,576,584,593,654,654,694,722,838,1833,1976,1979,1979,2002
           ,2004,2005,2045,2083,2109,2114,2126,2126,2157,2204,2204,2211,2212,2332,2576'
           , '\d+', 1, level)) id from dual connect by level < 5000
      )
      select * from tablename where tablename.id in (select id from list where id is not null);
      

      【讨论】:

        【解决方案4】:

        你可以这样使用:

        ... 
        where ',' || id_list || ',' like '%,' || to_char(id) || ',%'
        

        您确实需要在 to_char(id) 周围添加逗号(否则 3854 将匹配 38),并且您需要在 id_list 周围添加逗号以便第一个和最后一个值匹配(仅需要 id_list 周围的逗号因为你需要 to_char(id) 周围的逗号)。

        这假定id 的数据类型为NUMBER。如果它已经是 VARCHAR2 或其他字符数据类型,则只需要 id 而不是 to_char(id)。 (严格来说,即使id 是 NUMBER,也不需要to_char(),但作为一种最佳实践,不应依赖隐式转换。)

        例子:

        with
             mytable(id, val) as (
               select 100, 'abc' from dual union all
               select 173, 'z'   from dual union all
               select 250, 'dvd' from dual union all
               select  30, 'vv'  from dual union all
               select 359, 'ghi' from dual
             ),
             test_data (id_list) as (
               select '67,122,173,256,284,285,288,289,291,294,296,298,301,320,346,359'
                 from dual
             )
        select mytable.* from mytable, test_data
        where ',' || id_list || ',' like '%,' || to_char(id) || ',%'
        ;
        
                ID VAL
        ---------- ---
               173 z
               359 ghi
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-14
          • 2018-03-23
          相关资源
          最近更新 更多