7

sp_executesql を使用しなくても問題なく動作するストアド プロシージャを更新しようとしました。同じ構造のテーブルが多数あり、それぞれに新しいストアドプロシージャを作成したくないため、テーブル名をパラメーターとして使用したいと考えています。

私が抱えている問題は、このバージョンはすべてのパラメーターを必要とするように見えることですが、以前のものは任意の数のパラメーターを受け入れました。たとえば、すべての WHERE パラメーターを削除して @TableName パラメーターのみを指定すると、問題なく動作します。例を探してみましたが、このようなものは見つかりません。テーブル名を解析するすべての例には、そのパラメーターのみがあります。

CREATE PROCEDURE cafgTenantNamesTEST2
    @TableName sysname,
    @Square nvarchar(100) = null,
    @Location nvarchar(100) = null,
    @Name nvarchar(100) = null,
    @NormalizedName nvarchar(100) = null,
    @SharedLand int = 0,
    @FieldNumber int = 0,
    @Description nvarchar(255) = null,
    @Dwelling nvarchar(100) = null
AS
BEGIN
    DECLARE @sql AS NVARCHAR(MAX)
    SET @sql = 'SELECT * FROM [' + @TableName + ']' + 
    'WHERE ([Square] LIKE ''' + @Square + ''' OR ''' + @Square + ''' IS NULL)' + 
    'AND ([Location] = ''' + @Location + ''' OR ''' + @Location + ''' IS NULL)' +
    ...
    ...
--PRINT @sql
EXEC sp_executesql @sql
END

提案してください。

4

1 に答える 1

10

提案 1: QUOTENAME() を使用して、テーブル名の適切なエスケープを処理します。

提案 2: パラメータの値を @sql に挿入しています。そうしないでください。代わりに、パラメータ化された sql を使用する必要があります。

提案 3:クエリの WHERE 句を条件付きで作成して、OR ロジックを削除します。

 CREATE PROCEDURE cafgTenantNamesTEST2
    @TableName sysname,
    @Square nvarchar(100) = null,
    @Location nvarchar(100) = null,
    @Name nvarchar(100) = null,
    @NormalizedName nvarchar(100) = null,
    @SharedLand int = 0,
    @FieldNumber int = 0,
    @Description nvarchar(255) = null,
    @Dwelling nvarchar(100) = null
AS
BEGIN
    DECLARE @sql AS NVARCHAR(MAX)
    SET @sql = N'SELECT * FROM ' + QUOTENAME(@TableName ) + 
    ' WHERE 1=1 '
    IF  @Square IS NOT NULL
      SET @sql = @sql + ' AND ([Square] LIKE   @Square )'  -- still patameterized
   IF @Location IS NOT NULL
      SET @sql = @sql + N'  AND ([Location] = @Loc )'
    ...
    ...
--PRINT @sql
EXEC sp_executesql @sql, N'@Square nvarchar(100), @Loc nvarchar(100)...', @square=@square, @loc=@location  -- the param names can be the same or different, sp_executesql has it's own scope.
END

Sp_executesql は、プレーン SQL に加えてパラメーター化された SQL を実行できます。パラメーター化されたコードを実行するためにクライアント ライブラリによって使用されるのは、基になるシステム ストアド プロシージャです。たとえば、パラメーターを追加した場合、System.Data.SqlClient.SqlCommand は sp_executesql を呼び出します。可変数のパラメーターを受け入れるという点で、これは一般的ではありません。sp_executesqlに関する msdn ドキュメントは、いくつかの適切な情報を提供しますが、明確ではありません。sp_executesql の動作を確認する最も簡単な方法は、SQL プロファイラーでアクティビティをキャプチャすることです。

于 2013-06-15T03:21:34.033 に答える