sql >> データベース >  >> RDS >> Sqlserver

リストを含む変数を動的SQLクエリに渡すにはどうすればよいですか?

    単に

    EXECUTE ('select id from  [dbo].[CSVToTable] ('''[email protected]+''')')
            declare @listOfIDs varchar(1000);
    

    または、どちらがより良い方法です

    SET @listOfIDs = '5, 6, 7, 8, 9, 15, 28, 31, 49, 51, 59, 61'; 
    
    EXECUTE sp_executesql N'select id from  [dbo].[CSVToTable] (@listOfIDs)',
                          N'@listOfIDs VARCHAR(1000)',
                          @listOfIDs;
    
    • このエラーが発生するのはなぜですか?

    本当に多くのパラメータを渡すので、これを理解するには、このクエリを実行して、実際に関数に渡すものを確認してください。

    SELECT 'select id from  [dbo].[CSVToTable] ('[email protected]+')';
    

    これが返されます(これが実際に実行しようとしていることです)

    select id from  [dbo].[CSVToTable] (5, 6, 7, 8, 9, 15, 28, 31, 49, 51, 59, 61)
    

    代わりに(これが必要です)

    SELECT 'select id from  [dbo].[CSVToTable] ('''[email protected]+''')';
    
    • わかりました、でもなぜ sp_executesql execよりも優れています ?

    簡単に言うと、 EXEC すべての変数を1つの文字列に連結する必要があります。これは最悪の事態であり、コードをSQLインジェクションに対して完全にオープンにします。 。 <を参照してください。 code>キックする悪い習慣:sp_executesqlの代わりにEXEC()を使用する 、これは sp_executesqlという意味ではありません 100%安全ですが、ステートメントをパラメータ化することができます EXEC() そうではないため、 EXECよりも安全です。 SQLインジェクションの観点から

    最後に、タグを付けたので バージョンを指定しない場合は、 SPLIT_STRING() 関数(2016+)は自分のものよりもラタールです。2016+バージョンがない場合は、 WHILEを使用せずに独自のバージョンを作成してください。 より良いパフォーマンスを得るためにループし、 WHILEを引き起こします ループの実行は遅くなるため、回避する必要があります。

    例:



    1. ORA-06508:PL / SQL:呼び出されているプログラム・ユニットが見つかりませんでした

    2. MySQLWorkbenchをフェッチしています...-DBを参照できません

    3. MySQLの更新に(あまりにも)長い時間がかかる

    4. CentOS7でpostgresqlサービスを開始できません