1

私はmysqlclientを使用しています。

以下に示すように、私のクエリの1つで

sprintf (query, "select user from pcloud_session where id = '%s'", sid);

ここで、このsidには、例のように%記号が付いている場合があります

2Cq%yo4i-ZrizGGQGQ71eJQ0

しかし、この%がある場合、このクエリは常に失敗します。この%をエスケープする必要があると思いますが、どうすればよいですか?

\ と %% で試しましたが、どちらも機能しません。ここで助けてください

アップデート:

php セッションで session.hash_bits_per_character = 6 を使用する場合、デフォルトの文字セットには、常に URL コード化される文字 (カンマ) が含まれます (ここでは %2C)。これにより、Cookie 値にはこの %2C が含まれますが、セッション データベースには代わりにコンマが含まれます。この問題を解決するためのアイデアはありますか?..混乱して申し訳ありません

ありがとう

4

3 に答える 3

2

'%'MySQLクエリテキストのリテラルをエスケープする必要はありません。

クエリが「常に失敗する」と言うときmysql_query、エラーを返すのは関数の呼び出しですか?SQL例外コードを返しますか、それとも期待する結果セット(行)を返さないだけですか?

デバッグのためにquery、を呼び出した後、文字列の内容をエコーアウトすることをお勧めしますsprintf。文字列の内容は次のようになると予想されます。

select user from pcloud_session where id = '2Cq%yo4i-ZrizGGQGQ71eJQ0'

そして、そのSQL構造に問題はありません(id列が文字データ型に存在しpcloud_session、文字データ型であると仮定します。idが整数型として定義されている場合でも、そのステートメントは通常例外をスローしません。文字列リテラルは次のようになります。 2の整数値として解釈されます。)

'%'リテラルをsprintfのターゲット形式に含めても問題はありません。また、MySQLクエリテキスト内に「%」リテラルを含めても問題はありません。

(もちろん、関数sidの呼び出しによって入力されると想定していmysql_real_escape_stringます。)


query繰り返しになりますが、sprintfの呼び出しに続いて、の内容をエコーアウトすることをお勧めします。mysql_queryまた、他のコードがその文字列の内容をいじっていないことを確認することをお勧めします。これは、関数の引数として渡される実際の文字列です。(mysql_real_query関数を使用している場合は、正しい長さを渡していることを確認してください。)


アップデート

Oxiは次のように述べています。「SQL例外コードを返さず、期待する結果[セット]を返さないだけです。クエリを出力しました。%を含めて出力します。」

@Oxi

ここに、問題を突き止めるのに役立つ可能性のあるたくさんの質問があります。

mysqlコマンドラインクライアントからそのクエリテキストのテストを実行しましたか?それは期待する行を返しますか?

そのid列は、(少なくとも)24文字の長さのVARCHAR(またはCHAR)として定義されていますか?列の照合で大文字と小文字が区別されないように設定されていますか、それとも大文字と小文字が区別されますか?

show create table pcloud_session ;

(アプリケーションがデータベースの文字セットエンコーディングと一致しない場合、問題の原因となる可能性がありますが、文字セットの変換で問題を引き起こす文字はありません。)

そのid列に対してLIKE述語を使用してクエリをテストしましたか?

SELECT id, user FROM pcloud_session WHERE id LIKE '2Cq\%yo4i-%' ESCAPE '\\'
 ORDER BY id LIMIT 10 ;

SELECT id, user FROM pcloud_session WHERE id LIKE '2Cq%'
 ORDER BY id LIMIT 10 ;

1行を期待しているときに、行が返されませんか?返される行が多すぎますか、それとも予想とは異なる行を取得していますか?

idこれは、列の奇妙な値です。最初は、値がbase-64エンコーディングで表されているように見えますが、「%」と「-」の文字が含まれているため、標準のエンコーディングではありません。

于 2012-12-20T18:40:00.257 に答える
0

あなたは本当に自分で文字列をエスケープするべきではありません。最も安全なオプションは、MySQLAPIに処理させることです。

最大長nの文字列の場合、長さ2 * n+1の文字列を割り当てることから始めます。

int sidLength = strlen(sid);
// worst-case, we need to escape every character, plus a byte for the ASCIIZ
int maxSafeSidLength = sidLength * 2 + 1;
char *safeSid = malloc(maxSafeSidLength);

// copy "sid" to "safeSid", escaping as appropriate
mysql_real_escape_string(mysql, safeSid, sid, sidLength);


// build the query
// ...

free(safeSid);

dev.mysql.comのページには、クエリ文字列全体を作成する長い例がありmysql_real_escape_stringますが、上記のアプローチは、safeSidをsprintfに提供するために機能するはずです。

于 2012-12-20T18:49:47.767 に答える
0

インターフェイス ライブラリを使用せずに C でこれを行う場合は、 を使用して適切な SQL エスケープを行う必要があります。mysql_real_escape_string

MySQL 内で'% inside of a string, though, as the only context in which it has meaning is either directly inprintf LIKE ' を使用しても、本質的に問題はありません。type functions or as an argument to

これは本当に面倒ですが、絶対に必要です。コードが非常に複雑になるため、C で低レベルの MySQL を使用することは通常はお勧めできません。C++ ラッパーは、より多くのサポートを提供します。

于 2012-12-20T18:45:33.717 に答える