Aiuto Store procedure

giovedì 01 febbraio 2007 - 16.22

actarus1981 Profilo | Junior Member

Avrei la necessità di utilizzare in una store procedure come parametro utilizzato il nome della tabella... ma mi un errore quando esegui la procedura...

--> codice procedura

CREATE PROCEDURE dbo.Pippo
@Tabella nvarchar(20)
AS
SELECT * FROM [@Tabella]
GO

--> per eseguirla

EXEC dbo.Pippo "fin_liv1"

... purtroppo genera un errore

Server: Msg 208, Level 16, State 1, Procedure Pippo, Line 4
Invalid object name '@Tabella'.

Come posso fare?

Grazie

Fabio

lbenaglia Profilo | Guru

>Avrei la necessità di utilizzare in una store procedure come
>parametro utilizzato il nome della tabella... ma mi un errore
>quando esegui la procedura...

Ciao Fabio,

eggià, il nome di una tabella non è parametrizzabile.
Soluzione migliore: fai 1 sp per ogni tabella che devi interrogare.
Soluzione pericolosa, poco efficiente, bla bla...: utilizza il Dynamic SQL, ma prima leggi molto attentamente questo articolo di Erland:

"The Curse and Blessings of Dynamic SQL"
http://www.sommarskog.se/dynamic_sql.html

>Grazie
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

actarus1981 Profilo | Junior Member

Grazie, ho risolto! Ho modificato la procedura in questo modo, ed ora funziona esattamente come volevo:

CREATE PROCEDURE [dbo].[test] (
@tab varchar (50))
AS
EXEC ('
SELECT * FROM '+@tab+'
')

lbenaglia Profilo | Guru

>Grazie, ho risolto! Ho modificato la procedura in questo modo,
>ed ora funziona esattamente come volevo:
>
>CREATE PROCEDURE [dbo].[test] (
>@tab varchar (50))
>AS
>EXEC ('
>SELECT * FROM '+@tab+'
>')
>
>

Ne sei proprio sicuro?
Guarda come è semplice effettuare un attacco di SQL Injection con la tua stored procedure:

USE tempdb; CREATE TABLE dbo.Students( StudentID int NOT NULL IDENTITY PRIMARY KEY, FirstName varchar(10) NOT NULL, LastName varchar(10) NOT NULL ); INSERT dbo.Students VALUES('Lorenzo', 'Benaglia'); INSERT dbo.Students VALUES('Luca', 'Bianchi'); INSERT dbo.Students VALUES('Andrea', 'Montanari'); INSERT dbo.Students VALUES('Gianluca', 'Hotz'); GO CREATE PROCEDURE dbo.up_GetData( @Table sysname ) AS EXEC ('SELECT * FROM ' + @Table); GO EXEC dbo.up_GetData N'dbo.Students'; /* Output: StudentID FirstName LastName ----------- ---------- ---------- 1 Lorenzo Benaglia 2 Luca Bianchi 3 Andrea Montanari 4 Gianluca Hotz (4 row(s) affected) */ /* Simulo un attacco di SQL Injection */ EXEC dbo.up_GetData N'dbo.Students; DROP TABLE dbo.Students;'; /* Output: StudentID FirstName LastName ----------- ---------- ---------- 1 Lorenzo Benaglia 2 Luca Bianchi 3 Andrea Montanari 4 Gianluca Hotz (4 row(s) affected) */ EXEC dbo.up_GetData N'dbo.Students'; /* Output: Server: Msg 208, Level 16, State 1, Line 1 Invalid object name 'dbo.Students'. */ DROP PROCEDURE dbo.up_GetData;

Rileggi CON MOLTISSIMA ATTENZIONE l'articolo di Erland che ti ho indicato, ed evita di adottare soluzioni PERICOLOSE come quella che hai postato.
Mi spieghi che male c'è nello scrivere 10 o 100 stored procedure invece di 1 sola?
Oltre ad ottenere indubbi vantaggi prestazionali dovuti al riutilizzo dei piani di esecuzione, ti metteresti al riparo da questi gravi problemi di sicurezza.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

actarus1981 Profilo | Junior Member

Sul mio server i permessi di DROP li ha solamente l'utenza dell'aministratore, quindi nel caso del tuo codice, l'utente che esegue quella procedura dovrebbe loggarsi come sysadmin... ma a quel punto mi preoccuperei più di molte altre cose rispetto a cancellare una tabella! ...o perlomeno questo è quello che mi aspetto dai criteri di protezione adottati, ma essendo novizio parlando di MSSQL e soprattutto di store procedure, fammi sapere se sbaglio in qualche deduzione!!!

Per quanto rigurda invece il motivo che mi porta a creare una sola procedura invece che n da invocare, è che ho creato una base dati che ha una struttura comune di 9 tabelle, rigenerata per 20 volte per dividere i dati. L'aggiornamento delle tabelle avviene tramite un task sul server SQL: il mio intento è stato quello di creare un unico task che permettesse in base al nome del file di input, di capire quali tabelle dovesse aggiornare, e questo è il motivo dell'utilizzo di una store procedure così 'insicura'. In pratica, passo come parametro la radice della tabella da utilizzare (esempio fin_)... con questa variabile, il task opererà sulle 9 tabelle fin_*********.
Inoltre, penso che se un giorno dovessi modificare qualcosa nel processo o nelle tabelle o altro, modificare una procedura è molto più semplice e veloce che modificarne 100, stessa cosa per il task.. ne aggiorno 1 invece che 20!! Mi sembra sinceramente un approccio più scalabile per modifiche future...
... ribadisco comunque la mia poca esperienza in materia... e naturalmente ringrazio per ogni consiglio e scambio di opinioni!!!

Grazie

Fabio

lbenaglia Profilo | Guru

>Sul mio server i permessi di DROP li ha solamente l'utenza dell'aministratore,
>quindi nel caso del tuo codice, l'utente che esegue quella procedura
>dovrebbe loggarsi come sysadmin...
Ottimo, definire le giuste permission a livello di login/user account è la prima cosa da fare

>ma a quel punto mi preoccuperei
>più di molte altre cose rispetto a cancellare una tabella!
Tipo UPDATE/DELETE?

>Per quanto rigurda invece il motivo che mi porta a creare una
>sola procedura invece che n da invocare, è che ho creato una
>base dati che ha una struttura comune di 9 tabelle, rigenerata
>per 20 volte per dividere i dati.
Non entro nel merito dato che non conosco praticamente niente del tuo progetto, ma avere 9 tabelle praticamente identiche per dividere i dati non segue le linee guida ideali della progettazione di una base di dati

>Inoltre, penso che se un giorno dovessi modificare qualcosa nel
>processo o nelle tabelle o altro, modificare una procedura è
>molto più semplice e veloce che modificarne 100, stessa cosa
>per il task.. ne aggiorno 1 invece che 20!! Mi sembra sinceramente
>un approccio più scalabile per modifiche future...
Questo indubbiamente, ma analizza il discorso nel suo complesso, non solo dal punto di vista della manutenibilità.
Se si trattasse solo di questo, basterebbero un paio di script in croce per modificare in un lampo tutte le procedure...

>Grazie
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5