【问题标题】:Oracle query issue using concat || operator使用 concat 的 Oracle 查询问题 ||操作员
【发布时间】:2023-03-26 10:46:01
【问题描述】:

我正在尝试如下查询一个字符串。

目前我的 Oracle 表有大约 60 列。因此,针对所有列查询字符串将如下所示,

工作查询:

select * from <table_name> where (col1||col2||col3...||col60) like '%string%'

查询无效:

我又添加了一个查询来动态获取所有列,如下所示,

select * from <table_name> where (select LISTAGG(COLUMN_NAME, '||') WITHIN GROUP (ORDER BY COLUMN_NAME) from all_tab_columns where TABLE_NAME = '<table_name>' and OWNER = '<owner_name>' and DATA_TYPE != 'CLOB') like '%string%'

子查询:

下面的子查询没有问题。

select LISTAGG(COLUMN_NAME, '||') WITHIN GROUP (ORDER BY COLUMN_NAME) from all_tab_columns where TABLE_NAME = '<table_name>' and OWNER = '<owner_name>' and DATA_TYPE != 'CLOB'

子查询在哪里返回输出,就像在工作查询中一样。

我认为神谕采用“||”仅在硬编码时才使用 concat 运算符。

我可以尝试什么来解决这个问题?

【问题讨论】:

  • 这在 SQL 中从未被称为“管道”运算符。这仅在 unix shell 脚本中。
  • 你必须使用动态SQL来达到你想要的结果。您的第一个查询中的 col1||col2 正在获取列中的 VALUES 并将它们组合起来。您的第二个查询是组合 COLUMN 名称,而不是值,以与 %string% 进行比较。因此,您的第二个查询基本上是返回字符串 'Col1||Col2||Col3...' 并将其与 %string% 进行比较。这与第一个查询有很大不同。为了实现我认为你所追求的,你必须使第二个查询成为连接子查询结果的字符串,然后 execute (str);
  • 请注意,如果Col2 以st 结尾并且Col3 以ring 开头,则您的“工作”查询可能不匹配。您必须决定这是否有问题。
  • 如果您需要这样做,这可能表明设计错误。也许您应该重新考虑您的数据库模型。或者您可以考虑连接所有列的计算列,然后您只需要查询单个列。或者考虑使用 Oracle 的全文搜索功能

标签: sql oracle oracle11g oracle10g


【解决方案1】:

以下是我将如何以可扩展的方式解决您的问题。

CREATE OR REPLACE VIEW COLUMN_SEARCH AS

SELECT ID, COL1 AS COL
FROM TABLENAME

UNION ALL

SELECT ID, COL2 AS COL
FROM TABLENAME

UNION ALL

SELECT ID, COL3 AS COL
FROM TABLENAME

UNION ALL

SELECT ID, COL4 AS COL
FROM TABLENAME

UNION ALL

--- 

SELECT ID, COLN AS COL
FROM TABLENAME

现在有了这个视图,你的查询就是

SELECT TABLENAME.*
FROM TABLENAME
JOIN COLUMN_SEARCH ON TABLENAME.ID = COLUMN_SEARCH.ID
WHERE COLUMN_SEARCH.COL = 'string'

如果您需要它是动态的,那么只需在每次添加新列时更新视图。

如果它运行缓慢,那么只需在视图中对 ID、COL 进行索引。


基于 cmets 的更新

我想添加一些关于使用动态 SQL 来解决这个问题的 cmets。您可以使用动态 SQL 来解决此问题,但这不是一个好主意。 (对于那些不知道的人——每次运行查询时从有关列的元数据动态创建查询将使用动态 SQL)

这就是我不推荐它的原因:

  1. 动态 SQL 真的很难维护——它(根据定义)比非动态 SQL 更复杂,而且它看起来不像您真正尝试运行的查询。虽然它似乎会使维护更容易“每次我添加一个列时,它都会自动添加到 - bim-bamb-boom!”事实上,我发现每次添加列时最好选择“我要添加此列”。有时自动添加它会有所帮助,但很多时候它会破坏系统。

  2. 动态 SQL 中断优化 -- SQL 平台在其编译器中内置了数十年的优化,它们做得非常出色。因为动态 SQL 不能被每次编译和缓存,除了创建动态 SQL 所需的时间之外,您还会损失很多性能。

  3. 动态 SQL 不容易调整和调优 -- DBA 所做的很多工作就是查看数据模型的使用方式,然后添加索引、分区、具体化查询和其他调整以使系统快速运行。在动态 SQL 上进行这种调优要困难得多(但并非不可能)。

  4. 动态 SQL 是一种不好的代码气味 -- 这更微妙 可能不适用于这个特定问题,但需要说明 -- 如果你正在使用动态 sql,这可能表明您的数据模型有问题,或者您使用了错误的工具。有许多“nosql”系统可能更适合解决您的特定数据问题。

【讨论】:

  • 是的,我同意,但是当我将其应用于查询“Where”条件时,它给出了空结果集。
  • 这是因为字符串 'col1||col2||col3' 与文字 col1||col2||Col3 不同,其中 col1、col2 和 col3 的值将组合成 1 个值。然后将其与 %string% 进行比较。
  • @Yadheendran 让我重写以实际解决您的问题。
  • 如果同一行的多个列中存在相同的字符串,这将产生同一行的多个副本。并且视图仍然需要对列名进行硬编码,这首先是 OP 的问题。我看不出这对他有什么帮助。
  • @mathguy 如您所知, distinct 可以解决多行问题。这将对他有所帮助,因为它显示了在给定他拥有的数据模型的情况下为问题构建解决方案的正确方法。鉴于他告诉我们的内容以及 25 年以上的经验,我认为这是解决此问题的最佳方法(在可维护性和速度方面最好)。如果您有更好的答案,请发布答案-我很想学习新知识。
猜你喜欢
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
  • 2017-05-11
  • 2022-09-22
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
相关资源
最近更新 更多