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

时间:2010-07-20 08:30:53

标签: sql oracle search select metadata

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

例如,我知道,某些 未知 列的值为“xxx”且 多列 和表中的记录。

谢谢。

7 个答案:

答案 0 :(得分:9)


因此,您希望对数据库执行类似Google的自由文本搜索。这可以做到,但性能将是Teh Suck!谷歌很快,因为它的索引上有索引,有重复的数据存储,并且通常会优化所有内容以实现这种搜索。

无论如何,这是使用动态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是一个,呃,有趣前景。

我再说一次,表演将是Teh Suck!在大型数据集上。调整几乎是不可能的,因为我们不能索引每一列,当然也不支持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 ''%

答案 1 :(得分:2)

SELECT * FROM table WHERE column='xxx';

但是如果你有许多列可以包含这个值,你需要使用OR:

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

答案 2 :(得分:2)

如果您无法明确写出所有可能的列,则应使用架构dynamic SQL query生成metadata

答案 3 :(得分:1)

如果您需要这样做一次或两次,那么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在他的坟墓中旋转)

答案 4 :(得分:0)

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

这将显示属性XXX

的所有记录

答案 5 :(得分:-1)

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

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)

答案 6 :(得分:-1)

如果我需要在数据库中搜索某个值并且我不知道表和/或列,我通常会使用此脚本。只需设置@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