John Doe などの名前を含むデータベースがあります。残念ながら、これらの名前の一部には、Keiran O'Keefe などの引用が含まれています。今、次のような名前を検索しようとすると:
SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe'
私は(当然のことながら)エラーが発生します。
このエラーが発生しないようにするにはどうすればよいですか。Oracle と PLSQL を使用しています。
エスケープ文字は ' であるため、引用符を 2 つの引用符に置き換える必要があります。
例えば、
SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe'
になる
SELECT * FROM PEOPLE WHERE SURNAME='O''Keefe'
とはいえ、これを自分で行うのはおそらく正しくありません。お使いの言語には、SQL で使用するために文字列をエスケープする関数がある場合がありますが、さらに優れたオプションは、パラメーターを使用することです。通常、これは次のように機能します。
SQL コマンドは次のようになります。
SELECT * FROM PEOPLE WHERE SURNAME=?
次に、実行時に「O'Keefe」をパラメーターとして渡します。
パラメーター値が設定される前に SQL が解析されるため、パラメーター値が SQL の構造を変更する方法はありません (同じステートメントを異なるパラメーターで複数回実行する場合は、さらに高速になります)。
また、あなたの例ではエラーが発生するだけですが、文字列を適切にエスケープしないと、他の多くの問題が発生することにも注意してください。適切な出発点としてhttp://en.wikipedia.org/wiki/SQL_injectionを参照するか、次の古典的なxkcd コミックを参照してください。
Oracle10ソリューションは
SELECT * FROM PEOPLE WHERE SURNAME=q'{O'Keefe}'
パラメータ化されたSQLを使用すると、他にも利点があります。ステートメントを解析するためにOracleが必要とする作業量を減らすことで、OracleのCPUオーバーヘッド(およびその他のリソース)を削減します。パラメータを使用しない場合(Oracleではバインド変数と呼びます)、「select * from foo where bar='cat'」と「select*from foo where bar='dog'」は別々のステートメントとして扱われます。 select * from foo where bar =:b1"は同じステートメントです。つまり、構文、参照されるオブジェクトの有効性などを再度チェックする必要はありません。バインド変数を使用すると、通常、最も効率的なSQL実行プランが得られないという問題が発生することがありますが、これには回避策があり、これらの問題は、使用している述語によって異なります。
Matt が提案したように、パラメーター化されたクエリはあなたの友達です。
Command = SELECT * FROM PEOPLE WHERE SURNAME=?
彼らは関連する頭痛からあなたを守ります
入力フィルタリングは通常、データベース層ではなく言語レベルで行われます。
php と .NET の両方に、SQL ステートメントをエスケープするためのそれぞれのライブラリがあります。あなたの言語を確認してください。
データが信頼できる場合は、文字列置換を実行して ' の前に別の ' を追加してエスケープすることができます。入力が悪意のあるものであるというリスクがなければ、通常はこれで十分です。
良い質問だと思いますが、使用している言語は何ですか?
PHP では次のようにします: SELECT * FROM PEOPLE WHERE SURNAME='mysql_escape_string(O'Keefe)'
ただし、言語を指定しなかったため、エスケープ文字列関数 mysql を調べるか、言語で調べることをお勧めします。
Zend Framework を使用している場合に見積もりを処理するコードは次のとおりです。
$db = Zend_Db_Table_Abstract::getDefaultAdapter();
$db->quoteInto('your_query_here = ?','your_value_here');
例えば ;
//SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe' will become
SELECT * FROM PEOPLE WHERE SURNAME='\'O\'Keefe\''
Google で 30 歳未満で見つけた...