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

Hvordan skal jeg overføre et tabelnavn til en lagret proc?

Først og fremmest bør du ALDRIG lav SQL-kommandosammensætninger på en klientapp som denne, det er hvad SQL Injection er. (Det er OK for et administrationsværktøj, der ikke har sine egne privs, men ikke til et program til delt brug).

For det andet, ja, et parametriseret opkald til en lagret procedure er både renere og sikrere.

Men , da du skal bruge Dynamic SQL til at gøre dette, ønsker du stadig ikke at inkludere den beståede streng i teksten i den udførte forespørgsel. I stedet vil du bruge den beståede streng til at slå navnene op på den faktiske tabeller, som brugeren skal have lov til at forespørge på i vejen.

Her er et simpelt naivt eksempel:

CREATE PROC spCountAnyTableRows( @PassedTableName as NVarchar(255) ) AS
-- Counts the number of rows from any non-system Table, *SAFELY*
BEGIN
    DECLARE @ActualTableName AS NVarchar(255)

    SELECT @ActualTableName = QUOTENAME( TABLE_NAME )
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_NAME = @PassedTableName

    DECLARE @sql AS NVARCHAR(MAX)
    SELECT @sql = 'SELECT COUNT(*) FROM ' + @ActualTableName + ';'

    EXEC(@SQL)
END

Nogle har retfærdigt spurgt, hvorfor dette er sikrere. Forhåbentlig kan lille Bobby Tables gøre dette klarere:0

Svar på flere spørgsmål:

  1. QUOTENAME alene er ikke garanteret at være sikkert. MS opfordrer os til at bruge det, men de har ikke givet en garanti for, at det ikke kan overvindes af hackere. FYI, ægte sikkerhed handler om garantierne. Tabelopslaget med QUOTENAME er en anden historie, den er ubrydelig.

  2. QUOTENAME er ikke strengt nødvendigt for dette eksempel. Opslagsoversættelsen på INFORMATION_SCHEMA alene er normalt tilstrækkelig. QUOTENAME er med her, fordi det er en god form indenfor sikkerhed at inkludere en komplet og korrekt løsning. QUOTENAME herinde beskytter faktisk mod et særskilt, men lignende potentielt problem kendt som latent injektion .

Jeg skal bemærke, at du kan gøre det samme med dynamiske kolonnenavne og INFORMATION_SCHEMA.COLUMNS bord.

Du kan også omgå behovet for lagrede procedurer ved i stedet at bruge en parameteriseret SQL-forespørgsel (se her:https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=netværksramme-4.8). Men jeg tror, ​​at lagrede procedurer giver en mere håndterbar og mindre fejltilbøjelig sikkerhedsfacilitet til sager som dette.



  1. Bulk indsæt med SQLAlchemy ORM

  2. Slet forespørgsel virker ikke i mysql

  3. Pas på vildledende data fra SET STATISTICS IO

  4. Opdatering af SQL Server-tabeller med færre afbrydelser ved hjælp af partitionsskift