0
0

More than 3 years have passed since last update.

sp_executesqlを使用してエスケープ処理を行った

Posted at

テスト中に画面でエラーが発生してしまった。

調査の結果以下のような原因だった。

  • 検索条件に'(シングルクオーテーション)が含まれていてストアドプロシージャでエラーになっているようだ。

使用しているストアドでは動的sql※1(呼び方がわからないので以下このように呼びます。)を使用していた。

解決方法

以下の解決法が選択肢として上がりました。

  • ストアドプロシージャに渡すパラメータはすべてエスケープ処理を行う(SQLServerの場合はシングルクオーテーションをもう一つつける)
  • sp_executesqlの使用を検討する

検討の結果後者のsp_executesqlを使用することにしました。

実際にどのようなエラーだったか、
テストソースで解説します。

呼び出し元Java

 public static void callProcedure() throws SQLException {

        CallableStatement  cs = null;
        try (Connection con= DriverManager.getConnection(sqlcall.calltest())){
            cs = con.prepareCall("{? = call dbo.sp_TESTA(?)}");
            cs.registerOutParameter(1, java.sql.Types.INTEGER);
            cs.setString(2, "ff'ffff");
            cs.execute();
            ResultSet rs = cs.getResultSet();

            while(rs.next()) {
                System.out.println(rs.getString(1));
            }
            System.out.println("calltest"+ cs.getInt(1));

        }catch(SQLException e){
            e.printStackTrace();

        }
    }

testTableのデータ

Test1
ff'ffff
動的SQL※1


CREATE PROCEDURE [dbo].[sp_TESTA] 
    @TESTA nvarchar(40)
AS
BEGIN try
    -- SET NOCOUNT ON added to prevent extra result sets from
    SET NOCOUNT ON;

    DECLARE @query nvarchar(MAX) = '';
    DECLARE @parameters nvarchar(max) = '';



    SET @query = N' SELECT Test1 '
    SET @query = @query + N' FROM dbo.testTable '
    SET @query = @query + N' where Test1 = '''+ @TESTA+''''

    execute ( @query);

    return 0;

END try
begin catch

    SELECT   
        ERROR_NUMBER() AS ErrorNumber  
       ,ERROR_MESSAGE() AS ErrorMessage; 
    return  -1

end catch
GO


'ffff' 付近に不適切な構文があります。
calltest-1

文字内にある'(シングルクオーテーション)が文字の区切りとして認識され、後ろ4文字が文字として認識されませんでした。

これを以下のようにsp_executesqlを使用するように修正しました。

sp_executesql

CREATE PROCEDURE [dbo].[sp_TESTA] 
    -- Add the parameters for the stored procedure here
    @TESTA nvarchar(40)
AS
BEGIN try
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @query nvarchar(MAX) = '';
    DECLARE @parameters nvarchar(max) = '';


    SET @query = N' SELECT Test1 '
    SET @query = @query + N' FROM dbo.testTable '
    SET @query = @query + N' where Test1 = @Test1 '

    set @parameters = N'@Test1 nvarchar(40) '


    execute sp_executesql @query,@parameters, @Test1 = @TESTA

    return 0;

END try
begin catch

    SELECT   
        ERROR_MESSAGE() AS ErrorMessage; 
    return  -1

end catch
GO



ff'ffff
calltest0

無事文字として認識され正常に検索条件として反映されました。

まとめ

画面で渡された値を使用する場合にはsp_executesqlをなるべく使うこと。インジェクション対策にもつながるので、sp_executesqlで仕様を実装できるかを確認したほうが良い

参考

Microsoft SQLドキュメント sp_executesql (Transact-sql)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0