sql >> Database teknologi >  >> RDS >> Sqlserver

SQL Server - Vælg kolonner, der opfylder visse betingelser?

Jeg har oprettet en lagret procedure til dig.

Denne procedure undersøger MSSQL-metaen for at bygge en dynamisk SQL-streng, der returnerer et resultat, der indeholder kolonnenavne N og deres værdier V , og den tilsvarende rækketast K hvorfra denne værdi blev hentet, for en specificeret tabel.

Når dette udføres, gemmes resultaterne i en global midlertidig tabel kaldet ##ColumnsByValue, som derefter kan forespørges direkte.

Opret GetColumnsByValue lagret procedure ved at udføre dette script:

-- ============================================-- Forfatter:Ben Roberts (datex. )-- Oprettelsesdato:22. marts 2013-- Beskrivelse:Returnerer navnene på kolonner, der indeholder den angivne værdi, for en given række-- ============================================SÆT ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOIF OBJECT_ID ( 'dbo.GetColumnsByValue', 'P') ER IKKE NULL DROP PROCEDURE dbo.Getalue;GOCREATE PROCEDURE dbo.GetColumnsByValue -- Tilføj parametrene for den lagrede procedure her @idColumn sysname, @valueToFind nvarchar(255), @dbName sysname, @tableName sysname, @schemaName sysname, @debugMode int =0ASBEGINON SET -- SET for at forhindre ekstra resultatsæt i at forstyrre SELECT-sætninger. SÆT ANTAL TIL; DECLARE @SQL nvarchar(max); DECLARE @SQLUnion nvarchar(max); DECLARE @colName systemnavn; DECLARE @dbContext nvarchar(256); DECLARE @Union nvarchar(10); VÆLG @dbContext =@dbName + '.' + @schemaName + '.sp_executeSQL'; VÆLG @SQLUnion =''; VÆLG @Union =''; HVIS OBJECT_ID ( 'tempdb..##GetColumnsByValueIgnoreList') ER NULL -- der er ikke angivet nogen kolonner, der skal indlæses, skal du oprette en tom liste. BEGYND OPRET TABEL ##GetColumnsByValueIgnoreList (kolonnenavn nvarchar(255)); AFSLUT ERKLÆR DBcursor CURSOR FOR SELECT COLUMN_NAME FRA INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =@tabelnavn OG TABLE_SCHEMA =@skemanavn; ÅBN DBcursor; FETCH DBcursor INTO @colName; MENS (@@FETCH_STATUS =0) BEGYNDER HVIS ( @colName !=@idColumn OG @column NOT IN (SELECT column_name FROM ##GetColumnsByValueIgnoreList) ) BEGIN SELECT @SQL ='SELECT '[email protected] +' som K, '''[email protected] +''' som N, ' [email protected] + ' som V FRA ' + @dbName + '.' + @schemaName + '.' + @tabelnavn; --PRINT @SQL; VÆLG @SQLUnion =@SQL + @Union + @SQLUnion; SELECT @Union =' UNION '; END FETCH DBcursor INTO @colName; ENDE; -- mens CLOSE DBcursor; DEALLOCATE DBcursor; HVIS (@debugMode !=0) BEGYND UDSKRIV @SQLUnion; UDSKRIV @dbContext; END ELSE BEGIN -- Slet den midlertidige tabel, hvis den allerede er oprettet. HVIS OBJECT_ID ('tempdb..##ColumnsByValue') IKKE ER NULL BEGIN DROP TABLE ##ColumnsByValue END -- Opret en ny midlertidig tabel CREATE TABLE ##ColumnsByValue (K nvarchar(255), -- Key N nvarchar(255), -- Kolonnenavn V nvarchar(255) -- Kolonneværdi ) -- Udfyld den med resultaterne fra vores dynamisk genererede SQL. INSERT INTO ##ColumnsByValue EXEC @dbContext @SQLUnion; ENDENDGO

SP'en tager flere input som parametre, disse er forklaret i den følgende kode.

Bemærk også, at jeg har leveret en mekanisme til at tilføje en "ignoreringsliste" som input:

  • Dette giver dig mulighed for at angive alle kolonnenavne, der ikke bør inkluderes i resultaterne.
  • Du behøver IKKE at tilføje den kolonne, du bruger som din nøgle, dvs. row_id fra din eksempelstruktur.
  • Du SKAL inkludere andre kolonner, der ikke er varchar da disse vil forårsage en fejl (da SP bare laver en varchar sammenligning af alle kolonner, den ser på).
  • Dette gøres via en midlertidig tabel, som du skal oprette/udfylde
  • Dit eksempel på tabelstruktur antyder, at tabellen kun indeholder kolonner af interesse, så dette gælder muligvis ikke for dig.

Jeg har inkluderet eksempelkode for, hvordan du gør dette (men gør kun dette, hvis du bruger). til):

HVIS OBJECT_ID ( 'tempdb..##GetColumnsByValueIgnoreList') IKKE ER NULL BEGIN DROP TABEL ##GetColumnsByValueIgnoreList; ENDCREATE TABLE ##GetColumnsByValueIgnoreList (column_name nvarchar(255));INSERT INTO ##GetColumnsByValueIgnoreList VALUES ('a_column');INSERT INTO ##GetColumnsByValueIgnoreList /kode> 

For nu at afbryde proceduren, der opbygger din midlertidige resultattabel, skal du bruge følgende kode (og selvfølgelig ændre efter behov).

-- Byg ##ColumnsByValue-tabellenEXEC dbo.GetColumnsByValue @idColumn ='row_id', -- Navnet på kolonnen, der indeholder dit række-id (f.eks. sandsynligvis din PK-kolonne) @dbName ='dit_db_navn', @tableName ='dit_tabel_navn', @schemaName ='dbo', @debugMode =0 -- Indstil dette til 1, hvis du kun vil have en udskrift af den SQL, der blev brugt til at bygge temp-tabellen, til 0, hvis du vil have temp-tabellen udfyldt  

Dette efterlader dig med ##ColumnsByValue , hvor du kan udføre den søgning, du har brug for, f.eks.:

vælg * fra ##ColumnsByValue WHERE v ='luksus' og k =5 --some_row_id 

Du skal genudføre den lagrede procedure (og hvis det er relevant, oprette/ændre ignoreringslistetabellen før den) for hver tabel, du vil undersøge.

Et problem med denne tilgang er, at nvarchar-længden kan blive overskredet i dit tilfælde. Du ville prob. skal bruge en anden datatype, reducere kolonnenavnslængderne osv. Eller opdele det i undertrin og samle resultaterne for at få det resultatsæt, du leder efter.

En anden bekymring, jeg har, er, at dette er fuldstændig overkill for dit særlige scenarie, hvor et engangs script-til-forespørgsel-vindue vil give dig grundlaget for, hvad du har brug for, så vil noget smart tekstredigering i f.eks. Notepad++ give dig alle vejen dertil... og derfor vil dette problem sandsynligvis (og ganske rimeligt) udsætte dig for at gøre det på denne måde! Men det er et godt generelt spørgsmål, og fortjener derfor et svar til alle interesserede i fremtiden;-)




  1. Skift en partition ud i SQL Server (T-SQL)

  2. Kan nogen forklare, hvad MERGE-erklæringen virkelig gør i Oracle?

  3. hvordan man implementerer en kompliceret sql-kommando

  4. MYSQL:Hvordan finder man player_id fra efternavnet?