Anche se mi piacerebbe dare consigli su SQL dinamico in generale, in questo caso penso che si possa farla franca controllando se la variabile @Table contiene un nome di tabella valido.
- La domanda è se si ha intenzione di permettere nomi di schema e/o query cross-db, io' a patto che non vuole andare fuori del db (o server) qui, ma non consentono di diverso schema di (AdventureWorks mostra come possono essere utilizzati)
- POTREBBE anche includere le visualizzazioni per @Table.
- Probabilmente sarebbe "bello" se si controllasse anche se l'oggetto trovato avesse effettivamente una colonna ID e generato un errore "userfriendly" in caso contrario. Opzionale però.
Basta inserire QuoteName() intorno a @table NON ti proteggerà da tutto.Nonostante una grande funzione, è tutt'altro che perfetta. IMHO la soluzione migliore sarebbe analizzare la variabile @Table, controllare se il suo contenuto è valido e quindi creare SQL dinamico in base alle parti ottenute. Ho iniziato a fare la maggior parte di sopra e sorprendentemente non richiede un sacco di verifica di qualcosa che sembra semplice come questo =)
CREATE PROCEDURE [dbo].[GetDataByID] (
@ID bigint,
@Table nvarchar(300)
)
AS
DECLARE @sql nvarchar(max)
DECLARE @server_name sysname,
@db_name sysname,
@schema_name sysname,
@object_name sysname,
@schema_id int
SELECT @server_name = ParseName(@Table, 4),
@db_name = ParseName(@Table, 3),
@schema_name = ParseName(@Table, 2),
@object_name = ParseName(@Table, 1)
IF ISNULL(@server_name, @@SERVERNAME) <> @@SERVERNAME
BEGIN
RaisError('Queries are restricted to this server only.', 16, 1)
Return(-1)
END
IF ISNULL(@db_name, DB_Name()) <> DB_Name()
BEGIN
RaisError('Queries are restricted to this database only.', 16, 1)
Return(-1)
END
IF @schema_name IS NULL
BEGIN
IF NOT EXISTS (SELECT *
FROM sys.objects
WHERE name = @object_name
AND type IN ('U', 'V'))
BEGIN
RaisError('Requested @Table not found. [%s]', 16, 1, @object_name)
Return(-1)
END
SELECT @sql = 'SELECT * FROM ' + QuoteName(@object_name) + ' WHERE ID = @ID'
END
ELSE
BEGIN
SELECT @schema_id = Schema_id(@schema_name)
IF @schema_id IS NULL
BEGIN
RaisError('Unrecognized schema requested [%s].', 16, 1, @schema_name)
Return(-1)
END
IF NOT EXISTS (SELECT *
FROM sys.objects
WHERE name = @object_name
AND schema_id = @schema_id
AND type IN ('U', 'V'))
BEGIN
RaisError('Requested @Table not found. [%s].[%s]', 16, 1, @schema_name, @object_name)
Return(-1)
END
SELECT @sql = 'SELECT * FROM ' + QuoteName(@schema_name) + '.' + QuoteName(@object_name) + ' WHERE ID = @ID'
END
EXEC sp_executesql @stmt = @sql,
@params = N'@ID bigint',
@ID = @ID
Return(0)
Supra compila, ma potrebbe essere necessario appianare alcuni bug come io didn' t abbastanza per quanto riguarda il controllo di tutti i percorsi di codice.
Solo una piccola cosa che non influisce molto sulle cose, ma non è il parametro '@ Table' che è il problema qui? '@ ID' è un' bigint', quindi può essere solo un numero quando si raggiunge il punto di costruzione dell'istruzione SQL dinamica, giusto? –
Suppongo che entrambi .. –