一般的に私は動的SQLに対してアドバイスをしていますが、この場合は@Table変数に有効なテーブル名が含まれているかどうかを調べることでそれを取り除くことができます。
- 質問は、スキーマ名やクロスdbクエリを許可する予定がある場合は、ここでdb(またはサーバー)から外に出たくないと思っていますが、別のスキーマ(AdventureWorksは、その使い方を示しています)
- @Tableのビューも含める必要があります。
- 見つかったオブジェクトに実際にID列があるかどうかをチェックし、そうでない場合は 'userfriendly'エラーがスローされたとします。しかし、オプションです。
QuoteName()を@tableの周りに置くだけでは、あなたをすべてから守ることはできません。優れた機能はありますが、完璧ではありません。 IMHOあなたの最善の策は@Table変数を解析し、その内容が有効かどうかを確認し、得られた部分に基づいて動的SQLを作成することです。 は私が
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)
スープラのコンパイル)=それは、このような単純なに見える何かをチェックするの多くを必要以上と驚くほどそこのほとんどをやって始まったが、私は「didnのようあなたはいくつかのバグをアイロンをする必要がある場合がありますすべてのコードパスを調べる限りはかなり進んでいます。
多くのことに影響を与えない小さなものですが、ここで問題となる '@ Table'パラメータはありません。 '@ID'は' bigint'なので、動的SQL文を作成する時点に達したときだけ数値にすることができます。 –
私は両方とも.. –