SQL 选择可能包含特定值的所有记录

发布于 2024-09-10 17:46:23 字数 177 浏览 7 评论 0原文

如何在 SQL 表达式中选择可能包含已知特定值的所有记录,而不引用特定列

例如,我知道,一些未知列保存值“xxx”,并且有许多列和记录在表中。

谢谢。

How to select all records,that may contain specific value that is known, without referring to specific column in SQL expression?

For instance, i know,that some unknown column holds value 'xxx' and there are many columns and records in table.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

绮筵 2024-09-17 17:46:23

因此,您希望对数据库进行类似 Google 的自由文本搜索。这是可以做到的,但是性能会很糟糕!谷歌速度很快,因为它的索引上有索引,重复的数据存储,并且通常针对这种搜索优化一切。

无论如何,这是使用动态 SQL 和 Oracle 数据字典的概念证明。请注意,我将列限制为我想要搜索的数据类型,即字符串。

SQL> set serveroutput on size unlimited
SQL> declare
  2      dummy varchar2(1);
  3  begin
  4      for r in ( select table_name, column_name from user_tab_cols
  5                 where data_type in ('VARCHAR2', 'CHAR', 'CLOB') )
  6      loop
  7          begin
  8              execute immediate 'select null from '||r.table_name
  9                      ||' where '||r.column_name||' like ''%&search_value%'' '
 10                      ||' and rownum = 1'
 11                 into dummy;
 12              dbms_output.put_line('Found it in >>>'
 13                     ||r.table_name||'.'||r.column_name);
 14          exception
 15              when others then
 16                  -- bad practice ahoy!
 17                  null;
 18          end;
 19      end loop;
 20  end;
 21  /
Enter value for search_value: MAISIE
old   9:                ||' where '||r.column_name||' like ''%&search_value%'' '
new   9:                ||' where '||r.column_name||' like ''%MAISIE%'' '
Found it in >>>T23.NAME

PL/SQL procedure successfully completed.

SQL>

更强大的实现可能需要处理大小写、整个单词等。如果您使用的是 10g 或更高版本,那么正则表达式可能会很有用,但是将正则表达式和动态 SQL 结合起来是一个,呃,有趣的前景。

我再说一遍,表演将会很糟糕!在大数据集上。实际上不可能进行调整,因为我们无法对每一列建立索引,当然也不支持 LIKE 或类似的模糊匹配。另一种方法是使用 XQuery 生成数据的 XML 表示形式,然后使用 Text 对其进行索引。维护这样的存储库会产生一定的开销,但如果您定期需要此功能,尤其是在生产环境中,那么这项工作将是一项合理的投资。


我们可以使用 all_tab_cols 来对我们拥有权限的所有表进行更广泛的搜索。

for r in ( select owner, table_name, column_name from all_tab_cols
                   where data_type in ('VARCHAR2', 'CHAR', 'CLOB') )

显然,我们需要在生成的语句中添加所属模式的前缀。

execute immediate 'select null from '||r.owner||'.'||r.table_name
                       ||' where '||r.column_name||' like ''%

So, you want to do a Google-like free text search over your database. This can be done but the performance will be Teh Suck! Google is fast because it has indexes on its indexes, duplicate data stores and generally optimizes everything for precisely this kind of search.

Anyway, here is a proof of concept using dynamic SQL and the Oracle data dictionary. Note that I restrict the columns to the type of data I want to search for i.e. strings.

SQL> set serveroutput on size unlimited
SQL> declare
  2      dummy varchar2(1);
  3  begin
  4      for r in ( select table_name, column_name from user_tab_cols
  5                 where data_type in ('VARCHAR2', 'CHAR', 'CLOB') )
  6      loop
  7          begin
  8              execute immediate 'select null from '||r.table_name
  9                      ||' where '||r.column_name||' like ''%&search_value%'' '
 10                      ||' and rownum = 1'
 11                 into dummy;
 12              dbms_output.put_line('Found it in >>>'
 13                     ||r.table_name||'.'||r.column_name);
 14          exception
 15              when others then
 16                  -- bad practice ahoy!
 17                  null;
 18          end;
 19      end loop;
 20  end;
 21  /
Enter value for search_value: MAISIE
old   9:                ||' where '||r.column_name||' like ''%&search_value%'' '
new   9:                ||' where '||r.column_name||' like ''%MAISIE%'' '
Found it in >>>T23.NAME

PL/SQL procedure successfully completed.

SQL>

A more robust implementation might need to handle case, whole words, etc. If you're on 10g or higher then regular expressions could be useful, but combining regex and dynamic SQL is an, er, interesting prospect.

I repeat that performance is going to be Teh Suck! on a large data set. It is virtually impossible to tune, because we cannot index every column, and certainly not to support LIKE or similar fuzzy matches. An alternative approach would be to use XQuery to generate an XML representation of your data and then use Text to index it. Maintaining such a repository would be overhead, but the effort would be a sound investment if you need this functionality of a regular basis, especially in a production environment.


We can conduct a broader search across all the tables we have privileges on by using all_tab_cols instead.

for r in ( select owner, table_name, column_name from all_tab_cols
                   where data_type in ('VARCHAR2', 'CHAR', 'CLOB') )

Obviously we need to prefix the owning schema in the generated statement.

execute immediate 'select null from '||r.owner||'.'||r.table_name
                       ||' where '||r.column_name||' like ''%
温折酒 2024-09-17 17:46:23
SELECT * FROM table WHERE column='xxx';

但如果有很多列可以包含该值,则需要使用 OR:

SELECT * FROM table WHERE column1='xxx' or column2='xxx' or column3='xxx';
SELECT * FROM table WHERE column='xxx';

But if you have many columns which can contain this value, you need to use OR:

SELECT * FROM table WHERE column1='xxx' or column2='xxx' or column3='xxx';
标点 2024-09-17 17:46:23

如果您无法显式写入所有可能的列,则应生成 使用架构 的动态 SQL 查询元数据。

If you cannot explicitly write all the possible columns, you should generate a dynamic SQL query using the schema metadata.

说好的呢 2024-09-17 17:46:23

如果您需要执行一次或两次,那么 APC 的答案很好。如果这在某种程度上(令人震惊)是持续需求的一部分,那么我认为您能做的最好的事情就是在一个或多个感兴趣的表上创建一个 Oracle 计算字段并对其进行搜索。使用您确定不会出现在实际文本值中的分隔符,例如:

alter table mytable add search_column 
 as (mycolumn1||'^'||mycolumn2||'^'||mycolumn3);

现在您的查询变成如下所示:(

select <whatever transformation you want to see here> 
from mytable where search_column like '%^xxx^%'

您可能刚刚听到的声音是 Codd 在他的坟墓中旋转)

If you need to do this once or twice then APC's answer is good. If this is somehow (shudder) part of an ongoing requirement, then I think the best you'll be able to do is to create an Oracle computed field on the table or tables of interest and search on that. Use a delimiter that you're sure won't show up in the actual text values, e.g.:

alter table mytable add search_column 
 as (mycolumn1||'^'||mycolumn2||'^'||mycolumn3);

Now your query becomes something like:

select <whatever transformation you want to see here> 
from mytable where search_column like '%^xxx^%'

(That sound you may have just heard was Codd spinning in his grave)

半世蒼涼 2024-09-17 17:46:23

select * from table_name where(Table_Attribute='XXX');

这将显示具有属性 XXX 的所有记录

select * from table_name where(Table_Attribute='XXX');

this will show you all records with attribute XXX

爱她像谁 2024-09-17 17:46:23

运行此命令以获得所需的结果,请原谅使用了错误的命名。

declare @_var nvarchar(1000)
declare @var1 nvarchar(1000)
declare @var2 nvarchar(1000)
declare _cur cursor 
for select 

case Column_name 
            when '' then '' 
            else Column_name+'=''asd'' OR ' 
        end 
from information_schema.columns 
    where table_name='M_Patient' 
            and 
          data_type ='nvarchar'

open _cur
fetch _cur into @_var
while(@@fetch_status=0)
begin
set @var2=isnull(@var2,'')+@_var
fetch _cur into @_var

end
close _cur
deallocate _cur

set @var1='select * from M_Patient where '+ substring(@var2, 0,len(@var2)-2)

execute (@var1)

Run this to get desired result, sry for bad naming used.

declare @_var nvarchar(1000)
declare @var1 nvarchar(1000)
declare @var2 nvarchar(1000)
declare _cur cursor 
for select 

case Column_name 
            when '' then '' 
            else Column_name+'=''asd'' OR ' 
        end 
from information_schema.columns 
    where table_name='M_Patient' 
            and 
          data_type ='nvarchar'

open _cur
fetch _cur into @_var
while(@@fetch_status=0)
begin
set @var2=isnull(@var2,'')+@_var
fetch _cur into @_var

end
close _cur
deallocate _cur

set @var1='select * from M_Patient where '+ substring(@var2, 0,len(@var2)-2)

execute (@var1)
挽心 2024-09-17 17:46:23

如果我需要在数据库中搜索值并且我不知道表和/或列,我通常会使用此脚本。只需设置@SearcStr参数并推送播放即可。也许它可以帮助你。

DROP TABLE #Results

DECLARE @SearchStr nvarchar(100)
SET     @SearchStr = ''

CREATE TABLE 
    #Results(ColumnName nvarchar(370), ColumnValue nvarchar(3630))

SET NOCOUNT ON
DECLARE @TableName nvarchar(256)
DECLARE @ColumnName nvarchar(128)
DECLARE @SearchStr2 nvarchar(110)

SET @TableName = ''
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')

WHILE @TableName IS NOT NULL
BEGIN
    SET @ColumnName = ''
    SET @TableName = 
    (
        SELECT 
            MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
        FROM    
            INFORMATION_SCHEMA.TABLES
        WHERE
                TABLE_TYPE = 'BASE TABLE'
            AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
            AND OBJECTPROPERTY(OBJECT_ID(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)), 'IsMSShipped') = 0)

    WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
    BEGIN
        SET @ColumnName =
        (
            SELECT 
                MIN(QUOTENAME(COLUMN_NAME))
            FROM    
                INFORMATION_SCHEMA.COLUMNS
            WHERE           
                    TABLE_SCHEMA = PARSENAME(@TableName, 2)
                AND TABLE_NAME  = PARSENAME(@TableName, 1)
                AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
                AND QUOTENAME(COLUMN_NAME) > @ColumnName
        )

        IF @ColumnName IS NOT NULL
        BEGIN
            INSERT INTO #Results
            EXEC
            (
                'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
                FROM ' + @TableName + ' (NOLOCK) ' +
                ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
            )
        END
    END 
END

SELECT 
    ColumnName
   ,ColumnValue 
FROM 
    #Results

I usually use this script if I need to search for a value in a database and I don't know the table and/or column. Just set the @SearcStr parameter and push play. Maybe it can help you along.

DROP TABLE #Results

DECLARE @SearchStr nvarchar(100)
SET     @SearchStr = ''

CREATE TABLE 
    #Results(ColumnName nvarchar(370), ColumnValue nvarchar(3630))

SET NOCOUNT ON
DECLARE @TableName nvarchar(256)
DECLARE @ColumnName nvarchar(128)
DECLARE @SearchStr2 nvarchar(110)

SET @TableName = ''
SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')

WHILE @TableName IS NOT NULL
BEGIN
    SET @ColumnName = ''
    SET @TableName = 
    (
        SELECT 
            MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
        FROM    
            INFORMATION_SCHEMA.TABLES
        WHERE
                TABLE_TYPE = 'BASE TABLE'
            AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
            AND OBJECTPROPERTY(OBJECT_ID(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)), 'IsMSShipped') = 0)

    WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
    BEGIN
        SET @ColumnName =
        (
            SELECT 
                MIN(QUOTENAME(COLUMN_NAME))
            FROM    
                INFORMATION_SCHEMA.COLUMNS
            WHERE           
                    TABLE_SCHEMA = PARSENAME(@TableName, 2)
                AND TABLE_NAME  = PARSENAME(@TableName, 1)
                AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
                AND QUOTENAME(COLUMN_NAME) > @ColumnName
        )

        IF @ColumnName IS NOT NULL
        BEGIN
            INSERT INTO #Results
            EXEC
            (
                'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
                FROM ' + @TableName + ' (NOLOCK) ' +
                ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
            )
        END
    END 
END

SELECT 
    ColumnName
   ,ColumnValue 
FROM 
    #Results
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文