2010-07-20 21 views
2

Comment sélectionner tous les enregistrements, qui peuvent contenir une valeur spécifique connue, sans faire référence à la colonne spécifique dans l'expression SQL?Sélection SQL pour tous les enregistrements pouvant contenir une valeur spécifique

Par exemple, je sais que certains inconnu colonne contient la valeur « xxx » et il y a beaucoup de colonnes et enregistrements dans la table.

Merci.

+2

Juste un commentaire: Essayez d'éviter cela. SQL ne le permet pas directement (n'a pas de syntaxe spécifique pour cela) et même s'il existe des solutions de contournement avec SQL dynamique, les applications db robustes doivent rester simples et stupides, et le SQL dynamique cache la complexité qui se traduit tôt ou tard par des problèmes. termes de fonctionnalité inattendue, problèmes de performance et/ou problèmes de sécurité). – Unreason

+2

Vous souhaitez effectuer l'une des opérations les plus fondamentales dans un SGBD (c'est-à-dire appliquer une condition de recherche pour renvoyer un jeu de résultats), mais votre schéma vous en empêche. Je voudrais conclure que vous avez mal interprété le schéma ou le schéma est fatalement défectueux. – onedaywhen

+0

je vous remercie pour les réponses, je veux juste ajouter, que telle expression select je ne vais pas utiliser dans l'application, il me faut pour définir le mappage suivant: enregistrement à partir du fichier (entrée ASCII) -> colonne de DB existant – sergionni

Répondre

9

, vous voulez faire une recherche de texte libre de type Google sur votre base de données. Cela peut être fait mais la performance sera Teh Suck! Google est rapide car il possède des index sur ses index, duplique les magasins de données et optimise généralement tout pour précisément ce type de recherche.

Quoi qu'il en soit, voici une preuve de concept utilisant SQL dynamique et le dictionnaire de données Oracle. Notez que je limiter les colonnes au type de données que je veux rechercher, c'est-à-dire les chaînes.

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> 

Une implémentation plus robuste pourrait avoir besoin pour traiter les cas, des mots entiers, etc. Si vous êtes sur 10g ou plus alors des expressions régulières pourraient être utiles, mais la combinaison regex et SQL dynamique est un, euh, intéressant prospect.

Je répète que la performance va être Teh Suck! sur un grand ensemble de données. Il est pratiquement impossible de l'ajuster, car nous ne pouvons pas indexer chaque colonne, et certainement pas de prendre en charge LIKE ou des correspondances floues similaires. Une approche alternative consisterait à utiliser XQuery pour générer une représentation XML de vos données, puis utiliser Text pour l'indexer. Maintenir un tel référentiel serait une surcharge, mais l'effort serait un bon investissement si vous avez besoin de cette fonctionnalité de façon régulière, en particulier dans un environnement de production.

2
SELECT * FROM table WHERE column='xxx'; 

Mais si vous avez beaucoup de colonnes qui peuvent contenir cette valeur, vous devez utiliser OU:

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

essayé, a obtenu : ORA-00936: expression manquante 00936. 00000 - "expression manquante" – sergionni

+0

j'ai mentionné sélectionner requête sans se référer à une colonne spécifique, est-ce possible dans SQL.Peut-être, un mot-clé spécifique existe. – sergionni

+2

la question n'est pas de spécifier la colonne –

2

Si vous ne pouvez pas écrire explicitement toutes les colonnes possibles, vous devez générer un dynamic SQL query en utilisant le schéma metadata.

0

select * from nom_table où (Table_Attribute = 'XXX');

cela vous montrera tous les enregistrements avec attribut XXX

+0

sagar, que voulez-vous dire par TABLE_ATTRIBUTE? – sergionni

+0

thats le nom de votre colonne comme student_Id –

+0

ou comme Student_Name = 'XXX' –

-1

Exécuter ce pour obtenir le résultat souhaité, SRY pour la mauvaise appellation utilisée.

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,'')[email protected]_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) 
+0

qu'est-ce que Column_name? – sergionni

+0

@sergionni: c'est une méta-donnée stockée dans le serveur SQL. écrire une requête dans AS- analyseur de requêtes sql server ** select * from INFORMATION_SCHEMA.COLUMNS ** et vous allez commencer à obtenir ce que vous devez faire pour interroger le résultat –

+0

a reçu l'erreur: ORA-00942: table ou vue n'existe pas – sergionni

-1

J'utilise généralement ce script si j'ai besoin de rechercher une valeur dans une base de données et que je ne connais pas la table et/ou la colonne. Réglez simplement le paramètre @SearcStr et appuyez sur play. Peut-être que cela peut vous aider.

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 
+0

La question est signalée [Oracle] et, malheureusement, votre requête ne pas utiliser le dictionnaire de données Oracle ou la syntaxe Oracle. – APC

+0

Je semble avoir perdu mes yeux - sry à ce sujet :) – ramad

1

Si vous avez besoin de faire ceci une ou deux fois, la réponse d'APC est bonne. Si cela est en quelque sorte (frissonnant) partie d'une exigence continue, alors je pense que le mieux que vous pourrez faire est de créer un champ calculé Oracle sur la table ou les tables d'intérêt et de recherche sur cela. Utilisez un délimiteur dont vous êtes sûr qu'il n'apparaîtra pas dans les valeurs de texte réelles, par ex.:

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

Maintenant, votre requête devient quelque chose comme:

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

(Ce son que vous avez peut-être entendu a été juste Codd retourner dans sa tombe)

+0

Ceci est une solution intelligente; J'aurais aimé y penser. (Vous le ferez, Oscar, vous le ferez). Il y a quelques problèmes. Tout d'abord, les colonnes virtuelles ont été introduites dans 11g donc ce n'est pas une solution viable pour quiconque sur une base de données antérieure. Le problème le plus grave est que les colonnes virtuelles sont soumises à la limite de 4 000 caractères pour les colonnes VARCHAR2. Plus longtemps et il lance 'ORA-54004' (qui savait que les numéros OERR sont allés aussi haut?). Actuellement, les colonnes virtuelles ne peuvent pas être des clobs. – APC

+0

@APC - vous avez raison - j'ai complètement négligé la limitation varchar2 qui réduit l'utilité pour les tables larges. Merci pour le pointeur vers 54004 - bon à savoir. – dpbradley