SQL インジェクションSQL Injection

適用対象:Applies to: はいSQL ServerSQL Server (サポートされているすべてのバージョン) yesSQL ServerSQL Server (all supported versions) はいAzure SQL データベースAzure SQL DatabaseYesAzure SQL データベースAzure SQL Database はいAzure SQL Managed InstanceAzure SQL Managed InstanceYesAzure SQL Managed InstanceAzure SQL Managed Instance はいAzure Synapse AnalyticsAzure Synapse AnalyticsyesAzure Synapse AnalyticsAzure Synapse Analytics はいParallel Data WarehouseParallel Data WarehouseyesParallel Data WarehouseParallel Data Warehouse適用対象:Applies to: はいSQL ServerSQL Server (サポートされているすべてのバージョン) yesSQL ServerSQL Server (all supported versions) はいAzure SQL データベースAzure SQL DatabaseYesAzure SQL データベースAzure SQL Database はいAzure SQL Managed InstanceAzure SQL Managed InstanceYesAzure SQL Managed InstanceAzure SQL Managed Instance はいAzure Synapse AnalyticsAzure Synapse AnalyticsyesAzure Synapse AnalyticsAzure Synapse Analytics はいParallel Data WarehouseParallel Data WarehouseyesParallel Data WarehouseParallel Data Warehouse

SQL インジェクションとは、後で SQL Server のインスタンスに渡して解析と実行の対象とする文字列に、悪意のあるコードが挿入される攻撃です。SQL injection is an attack in which malicious code is inserted into strings that are later passed to an instance of SQL Server for parsing and execution. SQL Server では、構文的に有効であれば受信したクエリがすべて実行されるため、SQL ステートメントを構成するすべてのプロシージャにおいて、インジェクションに対する脆弱性を検証する必要があります。Any procedure that constructs SQL statements should be reviewed for injection vulnerabilities because SQL Server will execute all syntactically valid queries that it receives. 高いスキルを持つ決然たる攻撃者は、パラメーター化されたデータであっても操作できるのです。Even parameterized data can be manipulated by a skilled and determined attacker.

SQL インジェクションのしくみHow SQL Injection Works

SQL インジェクションは主に、SQL コマンドと連結されて実行されるユーザー入力変数にコードを直接挿入することにより行われます。The primary form of SQL injection consists of direct insertion of code into user-input variables that are concatenated with SQL commands and executed. それほど直接的ではない攻撃では、悪意のあるコードが、テーブル内の記憶領域に格納される文字列に挿入されたり、メタデータとして挿入されたりします。A less direct attack injects malicious code into strings that are destined for storage in a table or as metadata. 格納された文字列が動的な SQL コマンドに後で連結された場合、悪意のあるコードが実行されます。When the stored strings are subsequently concatenated into a dynamic SQL command, the malicious code is executed.

インジェクション プロセスは、途中でテキスト文字列を終了し、新しいコマンドを追加することによって行われます。The injection process works by prematurely terminating a text string and appending a new command. 挿入されたコマンドが実行される前に別の文字列が追加される可能性があるため、攻撃者は挿入する文字列をコメント記号 "--" で終了させます。Because the inserted command may have additional strings appended to it before it is executed, the malefactor terminates the injected string with a comment mark "--". 後続のテキストは実行時には無視されます。Subsequent text is ignored at execution time.

次のスクリプトは、単純な SQL インジェクションを示しています。The following script shows a simple SQL injection. ハードコードされた文字列とユーザー入力の文字列を連結することによって、SQL クエリが作成されます。The script builds an SQL query by concatenating hard-coded strings together with a string entered by the user:

var Shipcity;  
ShipCity = Request.form ("ShipCity");  
var sql = "select * from OrdersTable where ShipCity = '" + ShipCity + "'";  

ユーザーは、都市の名前を入力するように要求されます。The user is prompted to enter the name of a city. ユーザーが「 Redmond」と入力した場合、スクリプトによって構築されたクエリは次のようになります。If she enters Redmond, the query assembled by the script looks similar to the following:

SELECT * FROM OrdersTable WHERE ShipCity = 'Redmond'  

ただし、ユーザーが次のように入力するとします。However, assume that the user enters the following:

Redmond'; drop table OrdersTable--  

この場合、スクリプトによって構築されたクエリは次のようになります。In this case, the following query is assembled by the script:

SELECT * FROM OrdersTable WHERE ShipCity = 'Redmond';drop table OrdersTable--'  

セミコロン (;) は、前のクエリの終了と次のクエリの開始の区切りを示します。The semicolon (;) denotes the end of one query and the start of another. 2 つのハイフン (--) は、現在行の残りの部分はコメントであるため無視されることを意味します。The double hyphen (--) indicates that the rest of the current line is a comment and should be ignored. 変更されたコードが構文的に正しい場合、このコードはサーバーによって実行されます。If the modified code is syntactically correct, it will be executed by the server. SQL ServerSQL Server がこのステートメントを処理する場合、 SQL ServerSQL Server はまず OrdersTable から、 ShipCityRedmondであるレコードをすべて選択します。When SQL ServerSQL Server processes this statement, SQL ServerSQL Server will first select all records in OrdersTable where ShipCity is Redmond. その後、 SQL ServerSQL ServerOrdersTableを削除します。Then, SQL ServerSQL Server will drop OrdersTable.

挿入された SQL コードが構文的に正しい限り、改ざんをプログラムによって検出するのは不可能です。As long as injected SQL code is syntactically correct, tampering cannot be detected programmatically. このため、すべてのユーザー入力を検証し、使用しているサーバーで作成された SQL コマンドを実行するコードを注意深く確認する必要があります。Therefore, you must validate all user input and carefully review code that executes constructed SQL commands in the server that you are using. このトピックの次のセクションでは、コーディングのベスト プラクティスについて説明します。Coding best practices are described in the following sections in this topic.

すべての入力の検証Validate All Input

型、長さ、形式、および範囲をテストすることによってユーザー入力を必ず検証してください。Always validate user input by testing type, length, format, and range. 悪意のある入力を未然に防ぐには、アプリケーションのアーキテクチャおよび配置シナリオについて検討する必要があります。When you are implementing precautions against malicious input, consider the architecture and deployment scenarios of your application. セキュリティで保護された環境で実行するようにデザインされたプログラムでも、セキュリティで保護されていない環境にコピーされる可能性があることに注意してください。Remember that programs designed to run in a secure environment can be copied to an nonsecure environment. 次の提案をベスト プラクティスとして検討してください。The following suggestions should be considered best practices:

  • アプリケーションによって受信されるデータのサイズ、型、内容を推測で処理しない。Make no assumptions about the size, type, or content of the data that is received by your application. たとえば、次のような評価を行う必要があります。For example, you should make the following evaluation:

    • 郵便番号の入力がアプリケーションから期待されている場所に対して、ユーザーの誤りあるいは悪意のあるユーザーによって 10 MB の MPEG ファイルが入力された場合、アプリケーションはどのような動作をするか。How will your application behave if an errant or malicious user enters a 10-megabyte MPEG file where your application expects a postal code?

    • DROP TABLE ステートメントがテキスト フィールドに埋め込まれている場合、アプリケーションはどのような動作をするか。How will your application behave if a DROP TABLE statement is embedded in a text field?

  • 入力のサイズとデータ型をテストし、適切な制限を適用する。Test the size and data type of input and enforce appropriate limits. これは、意図的なバッファー オーバーランを防ぐのに役立ちます。This can help prevent deliberate buffer overruns.

  • 文字列変数の内容をテストし、予測される値のみを受け入れる。Test the content of string variables and accept only expected values. バイナリ データ、エスケープ シーケンス、およびコメント文字を含む入力は拒否します。Reject entries that contain binary data, escape sequences, and comment characters. これは、スクリプト インジェクションを防ぐのに役立ち、バッファー オーバーランをねらった攻撃に対する防御にもなります。This can help prevent script injection and can protect against some buffer overrun exploits.

  • XML ドキュメントを扱う場合、入力時にすべてのデータをスキーマに照らして検証する。When you are working with XML documents, validate all data against its schema as it is entered.

  • Transact-SQLTransact-SQL ステートメントをユーザー入力から直接構築しない。Never build Transact-SQLTransact-SQL statements directly from user input.

  • ストアド プロシージャを使用して、ユーザー入力を検証する。Use stored procedures to validate user input.

  • 多層環境では、信頼関係ゾーンへ入る前にすべてのデータを検証する必要がある。In multitiered environments, all data should be validated before admission to the trusted zone. 検証プロセスをパスしないデータは拒否し、直前の層にエラーを返す必要があります。Data that does not pass the validation process should be rejected and an error should be returned to the previous tier.

  • 複数層の検証を実装する。Implement multiple layers of validation. 軽い悪意を持つユーザーに対する予防策は、決然たる攻撃者に対しては有効ではありません。Precautions you take against casually malicious users may be ineffective against determined attackers. より適切な実践方法は、ユーザー インターフェイスを介した入力時に検証を行い、その後の信頼境界を越えるすべてのポイントでも検証を行うことです。A better practice is to validate input in the user interface and at all subsequent points where it crosses a trust boundary.
    たとえば、クライアント側アプリケーションでのデータ検証によって、単純なスクリプト インジェクションを防ぐことができます。For example, data validation in a client-side application can prevent simple script injection. ただし、次の層で、この入力が既に検証済みであると推測されると、クライアントを迂回する能力を持つ悪意のあるユーザーは、システムへ無制限にアクセスできることになります。However, if the next tier assumes that its input has already been validated, any malicious user who can bypass a client can have unrestricted access to a system.

  • 検証されていないユーザー入力は連結しない。Never concatenate user input that is not validated. 文字列の連結は、スクリプト インジェクションを行うための主なポイントとなります。String concatenation is the primary point of entry for script injection.

  • ファイル名の作成に使用できるフィールドでは、次の文字列を受け付けない:AUX、CLOCK$、COM1 から COM8、CON、CONFIG$、LPT1 から LPT8、NUL、PRN。Do not accept the following strings in fields from which file names can be constructed: AUX, CLOCK$, COM1 through COM8, CON, CONFIG$, LPT1 through LPT8, NUL, and PRN.

可能であれば、次の文字を含む入力は受け入れないでください。When you can, reject input that contains the following characters.

入力文字Input character Transact-SQL での意味Meaning in Transact-SQL
;; クエリの区切り記号。Query delimiter.
' の基本構成の更新を依頼してください。' 文字データ文字列の区切り記号。Character data string delimiter.
-- 文字データ文字列の区切り記号。Character data string delimiter.
.
/* ... *//* ... */ コメントの区切り記号。Comment delimiters. /**/ の間にあるテキストについては、サーバーによる評価は行われません。Text between /* and */ is not evaluated by the server.
xp_xp_ xp_cmdshellなど、カタログ拡張ストアド プロシージャ名の先頭に使用します。Used at the start of the name of catalog-extended stored procedures, such as xp_cmdshell.

Type-Safe SQL パラメーターの使用Use Type-Safe SQL Parameters

SQL ServerSQL ServerParameters コレクションは、型のチェックおよび長さの検証に使用できます。The Parameters collection in SQL ServerSQL Server provides type checking and length validation. Parameters コレクションを使用する場合、入力は実行可能コードとしてではなくリテラル値として扱われます。If you use the Parameters collection, input is treated as a literal value instead of as executable code. Parameters コレクションを使用することのもう 1 つの利点は、型のチェックおよび長さのチェックを適用できることです。An additional benefit of using the Parameters collection is that you can enforce type and length checks. 範囲外の値が入力されると例外が発生します。Values outside the range will trigger an exception. 次のコード フラグメントは、 Parameters コレクションの使用方法を示しています。The following code fragment shows using the Parameters collection:

SqlDataAdapter myCommand = new SqlDataAdapter("AuthorLogin", conn);  
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;  
SqlParameter parm = myCommand.SelectCommand.Parameters.Add("@au_id",  
     SqlDbType.VarChar, 11);  
parm.Value = Login.Text;  

この例では、 @au_id パラメーターは実行可能コードとしてではなくリテラル値として扱われます。In this example, the @au_id parameter is treated as a literal value instead of as executable code. この値は型および長さについてチェックされます。This value is checked for type and length. @au_id の値が指定された型および長さの制約に従っていない場合は、例外がスローされます。If the value of @au_id does not comply with the specified type and length constraints, an exception will be thrown.

ストアド プロシージャとパラメーター化された入力の使用Use Parameterized Input with Stored Procedures

ストアド プロシージャがフィルターされていない入力を使用する場合、このストアド プロシージャは SQL インジェクションの影響を受けやすくなります。Stored procedures may be susceptible to SQL injection if they use unfiltered input. たとえば、次のコードには脆弱性があります。For example, the following code is vulnerable:

SqlDataAdapter myCommand =   
new SqlDataAdapter("LoginStoredProcedure '" +   
                               Login.Text + "'", conn);  

ストアド プロシージャを使用する場合、パラメーターをストアド プロシージャの入力として使用する必要があります。If you use stored procedures, you should use parameters as their input.

動的な SQL を使用した Parameters コレクションの使用Use the Parameters Collection with Dynamic SQL

ストアド プロシージャを使用できない場合でも、次のコード例に示すようにパラメーターを使用することができます。If you cannot use stored procedures, you can still use parameters, as shown in the following code example.

SqlDataAdapter myCommand = new SqlDataAdapter(  
"SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", conn);  
SQLParameter parm = myCommand.SelectCommand.Parameters.Add("@au_id",   
                        SqlDbType.VarChar, 11);  
Parm.Value = Login.Text;  

入力のフィルターFiltering Input

入力をフィルターすると、エスケープ文字が削除されることで SQL インジェクションの防御に役立ちます。Filtering input may also be helpful in protecting against SQL injection by removing escape characters. ただし、問題となり得る文字は数が多いため、信頼性の高い防御策にはなりません。However, because of the large number of characters that may pose problems, this is not a reliable defense. 次の例では、文字の文字列区切り記号を検索しています。The following example searches for the character string delimiter.

private string SafeSqlLiteral(string inputSQL)  
{  
  return inputSQL.Replace("'", "''");  
}  

LIKE 句LIKE Clauses

LIKE 句を使用している場合、ワイルドカード文字もエスケープする必要があることに注意してください。Note that if you are using a LIKE clause, wildcard characters still must be escaped:

s = s.Replace("[", "[[]");  
s = s.Replace("%", "[%]");  
s = s.Replace("_", "[_]");  

SQL インジェクションのコードの確認Reviewing Code for SQL Injection

EXECUTEEXEC、または sp_executesqlを呼び出すすべてのコードを確認する必要があります。You should review all code that calls EXECUTE, EXEC, or sp_executesql. 次のようなクエリを使用すると、これらのステートメントを含むプロシージャの識別に役立てることができます。You can use queries similar to the following to help you identify procedures that contain these statements. このクエリは、 EXECUTE または EXECという語の後に 1 ~ 4 個のスペースがあるかどうかをチェックします。This query checks for 1, 2, 3, or 4 spaces after the words EXECUTE or EXEC.

SELECT object_Name(id) FROM syscomments  
WHERE UPPER(text) LIKE '%EXECUTE (%'  
OR UPPER(text) LIKE '%EXECUTE  (%'  
OR UPPER(text) LIKE '%EXECUTE   (%'  
OR UPPER(text) LIKE '%EXECUTE    (%'  
OR UPPER(text) LIKE '%EXEC (%'  
OR UPPER(text) LIKE '%EXEC  (%'  
OR UPPER(text) LIKE '%EXEC   (%'  
OR UPPER(text) LIKE '%EXEC    (%'  
OR UPPER(text) LIKE '%SP_EXECUTESQL%';  

QUOTENAME() および REPLACE() でのパラメーターのラップWrapping Parameters with QUOTENAME() and REPLACE()

選択された各ストアド プロシージャで、動的な Transact-SQL で使用されるすべての変数が正しく処理されることを確認します。In each selected stored procedure, verify that all variables that are used in dynamic Transact-SQL are handled correctly. ストアド プロシージャの入力パラメーターから取得するデータ、またはテーブルから読み取るデータは、QUOTENAME() または REPLACE() でラップする必要があります。Data that comes from the input parameters of the stored procedure or that is read from a table should be wrapped in QUOTENAME() or REPLACE(). QUOTENAME() に渡される @variable の値のデータ型は sysname であり、文字列の最大長は 128 文字であることに注意してください。Remember that the value of @variable that is passed to QUOTENAME() is of sysname, and has a maximum length of 128 characters.

@variable@variable 推奨ラッパーRecommended wrapper
セキュリティ保護可能なリソースの名前Name of a securable QUOTENAME(@variable)
128 文字以下の文字列String of ≤128 characters QUOTENAME(@variable, '''')
128 文字より長い文字列String of > 128 characters REPLACE(@variable,'''', '''''')

この方法を使用すると、SET ステートメントを次のように変更できます。When you use this technique, a SET statement can be revised as follows:

-- Before:  
SET @temp = N'SELECT * FROM authors WHERE au_lname ='''   
 + @au_lname + N'''';  
  
-- After:  
SET @temp = N'SELECT * FROM authors WHERE au_lname = '''   
 + REPLACE(@au_lname,'''','''''') + N'''';  

データの切り捨てによって有効になるインジェクションInjection Enabled by Data Truncation

変数に代入されるすべての動的な Transact-SQLTransact-SQL は、その変数に割り当てられているバッファーよりも大きい場合は切り捨てられます。Any dynamic Transact-SQLTransact-SQL that is assigned to a variable will be truncated if it is larger than the buffer allocated for that variable. 予期しない長さの文字列をストアド プロシージャに渡すことで、強制的にステートメントの切り捨てを行うことができれば、攻撃者が結果を操作することも可能になります。An attacker who is able to force statement truncation by passing unexpectedly long strings to a stored procedure can manipulate the result. たとえば、次のスクリプトによって作成されるストアド プロシージャは、切り捨てによって有効になるインジェクションの影響を受けやすくなります。For example, the stored procedure that is created by the following script is vulnerable to injection enabled by truncation.

CREATE PROCEDURE sp_MySetPassword  
@loginname sysname,  
@old sysname,  
@new sysname  
AS  
-- Declare variable.  
-- Note that the buffer here is only 200 characters long.   
DECLARE @command varchar(200)  
-- Construct the dynamic Transact-SQL.  
-- In the following statement, we need a total of 154 characters   
-- to set the password of 'sa'.   
-- 26 for UPDATE statement, 16 for WHERE clause, 4 for 'sa', and 2 for  
-- quotation marks surrounded by QUOTENAME(@loginname):  
-- 200 - 26 - 16 - 4 - 2 = 154.  
-- But because @new is declared as a sysname, this variable can only hold  
-- 128 characters.   
-- We can overcome this by passing some single quotation marks in @new.  
SET @command= 'update Users set password='   
    + QUOTENAME(@new, '''') + ' where username='   
    + QUOTENAME(@loginname, '''') + ' AND password = '   
    + QUOTENAME(@old, '''')  
  
-- Execute the command.  
EXEC (@command)  
GO  

攻撃者は、sa の古いパスワードがわからなくても、128 文字バッファーに 154 文字を渡して新しいパスワードを設定できます。By passing 154 characters into a 128 character buffer, an attacker can set a new password for sa without knowing the old password.

EXEC sp_MySetPassword 'sa', 'dummy',   
'123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012'''''''''''''''''''''''''''''''''''''''''''''''''''   

このため、コマンド変数には大きなバッファーを使用するか、 Transact-SQLTransact-SQL は直接 EXECUTE ステートメント内で動的に実行する必要があります。For this reason, you should use a large buffer for a command variable or directly execute the dynamic Transact-SQLTransact-SQL inside the EXECUTE statement.

QUOTENAME(@variable, '''') および REPLACE() 使用時の切り捨てTruncation When QUOTENAME(@variable, '''') and REPLACE() Are Used

QUOTENAME() および REPLACE() から返される文字列は、割り当てられている領域よりも大きくなると、暗黙に切り捨てられます。Strings that are returned by QUOTENAME() and REPLACE() will be silently truncated if they exceed the space that is allocated. 次の例で作成されるストアド プロシージャは、行われる可能性がある処理を示しています。The stored procedure that is created in the following example shows what can happen.

CREATE PROCEDURE sp_MySetPassword  
    @loginname sysname,  
    @old sysname,  
    @new sysname  
AS  
  
-- Declare variables.  
    DECLARE @login sysname  
    DECLARE @newpassword sysname  
    DECLARE @oldpassword sysname  
    DECLARE @command varchar(2000)  
  
-- In the following statements, the data stored in temp variables  
-- will be truncated because the buffer size of @login, @oldpassword,  
-- and @newpassword is only 128 characters, but QUOTENAME() can return  
-- up to 258 characters.  
    SET @login = QUOTENAME(@loginname, '''')  
    SET @oldpassword = QUOTENAME(@old, '''')  
    SET @newpassword = QUOTENAME(@new, '''')  
  
-- Construct the dynamic Transact-SQL.  
-- If @new contains 128 characters, then @newpassword will be '123... n  
-- where n is the 127th character.   
-- Because the string returned by QUOTENAME() will be truncated,   
-- it can be made to look like the following statement:  
-- UPDATE Users SET password ='1234. . .[127] WHERE username=' -- other stuff here  
    SET @command = 'UPDATE Users set password = ' + @newpassword   
     + ' where username =' + @login + ' AND password = ' + @oldpassword;  
  
-- Execute the command.  
EXEC (@command);  
GO  

このため、次のステートメントでは、すべてのユーザーのパスワードを前のコードで渡された値に設定しますTherefore, the following statement will set the passwords of all users to the value that was passed in the previous code

EXEC sp_MyProc '--', 'dummy', '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678'  

REPLACE() を使用すると、割り当てられたバッファー領域よりも大きくすることで強制的に文字列の切り捨てを行うことができます。You can force string truncation by exceeding the allocated buffer space when you use REPLACE(). 次の例で作成されるストアド プロシージャは、行われる可能性がある処理を示しています。The stored procedure that is created in the following example shows what can happen.

CREATE PROCEDURE sp_MySetPassword  
    @loginname sysname,  
    @old sysname,  
    @new sysname  
AS  
  
-- Declare variables.  
    DECLARE @login sysname  
    DECLARE @newpassword sysname  
    DECLARE @oldpassword sysname  
    DECLARE @command varchar(2000)  
  
-- In the following statements, data will be truncated because   
-- the buffers allocated for @login, @oldpassword and @newpassword   
-- can hold only 128 characters, but QUOTENAME() can return   
-- up to 258 characters.   
    SET @login = REPLACE(@loginname, '''', '''''')  
    SET @oldpassword = REPLACE(@old, '''', '''''')  
    SET @newpassword = REPLACE(@new, '''', '''''')  
  
-- Construct the dynamic Transact-SQL.  
-- If @new contains 128 characters, @newpassword will be '123...n   
-- where n is the 127th character.   
-- Because the string returned by QUOTENAME() will be truncated, it  
-- can be made to look like the following statement:  
-- UPDATE Users SET password='1234...[127] WHERE username=' -- other stuff here   
    SET @command= 'update Users set password = ''' + @newpassword + ''' where username='''   
     + @login + ''' AND password = ''' + @oldpassword + '''';  
  
-- Execute the command.  
EXEC (@command);  
GO  

QUOTENAME() と同様に、すべての場合に対して十分な大きさである一時変数を宣言することで、REPLACE() による文字列の切り捨てを回避できます。As with QUOTENAME(), string truncation by REPLACE() can be avoided by declaring temporary variables that are large enough for all cases. 可能であれば、動的な Transact-SQLTransact-SQL内で QUOTENAME() または REPLACE() を直接呼び出すことをお勧めします。When possible, you should call QUOTENAME() or REPLACE() directly inside the dynamic Transact-SQLTransact-SQL. あるいは、必要なバッファー サイズを次のように計算できます。Otherwise, you can calculate the required buffer size as follows. @outbuffer = QUOTENAME(@input)の場合、 @outbuffer のサイズは 2*(len(@input)+1)にする必要があります。For @outbuffer = QUOTENAME(@input), the size of @outbuffer should be 2*(len(@input)+1). 前の例のように、 REPLACE() を使用し、二重引用符を繰り返すときは、バッファー サイズは 2*len(@input) で十分です。When you use REPLACE() and doubling quotation marks, as in the previous example, a buffer of 2*len(@input) is enough.

次の計算は、すべての場合に対応します。The following calculation covers all cases:

WHILE LEN(@find_string) > 0, required buffer size =  
ROUND(LEN(@input)/LEN(@find_string),0) * LEN(@new_string)   
 + (LEN(@input) % LEN(@find_string))  

QUOTENAME(@variable, ']') 使用時の切り捨てTruncation When QUOTENAME(@variable, ']') Is Used

SQL ServerSQL Server のセキュリティ保護可能なリソースの名前が QUOTENAME(@variable, ']')という形式のステートメントに渡されると、切り捨てが発生する可能性があります。Truncation can occur when the name of a SQL ServerSQL Server securable is passed to statements that use the form QUOTENAME(@variable, ']'). 次に例を示します。The following example shows this.

CREATE PROCEDURE sp_MyProc  
    @schemaname sysname,  
    @tablename sysname,  
AS  
  
-- Declare a variable as sysname. The variable will be 128 characters.  
-- But @objectname actually must allow for 2*258+1 characters.   
DECLARE @objectname sysname  
SET @objectname = QUOTENAME(@schemaname)+'.'+ QUOTENAME(@tablename)   
-- Do some operations.  
GO  

型 sysname の値を連結する場合、値ごとに最大 128 文字を十分保持できる大きさの一時変数を使用する必要があります。When you are concatenating values of type sysname, you should use temporary variables large enough to hold the maximum 128 characters per value. 可能であれば、動的な QUOTENAME() 内で Transact-SQLTransact-SQLを直接呼び出します。If possible, call QUOTENAME() directly inside the dynamic Transact-SQLTransact-SQL. あるいは、前述のように必要なバッファー サイズを計算できます。Otherwise, you can calculate the required buffer size as explained in the previous section.

参照See Also

EXECUTE (Transact-SQL) EXECUTE (Transact-SQL)
REPLACE (Transact-SQL) REPLACE (Transact-SQL)
QUOTENAME (Transact-SQL) QUOTENAME (Transact-SQL)
sp_executesql (Transact-SQL) sp_executesql (Transact-SQL)
SQL Server の保護Securing SQL Server