2

mysqlデータベースのbinary(16)フィールドにその識別子をGUIDとして格納するサードパーティの.NETライブラリ(Rhino Security)を使用しています。すべてがアプリケーションから完全に機能しますが、クエリエディタ(mysqlの場合はTOAD)を介して手動でクエリを実行しようとすると、存在することがわかっている識別子の行が返されません。たとえば、次のクエリを実行すると、結果が得られません。

SELECT Id, EntitySecurityKey, Type
FROM mydb.security_entityreferences 
where EntitySecurityKey  =  '02a36462-49b7-406a-a3b6-d5accd6695e5'

フィルタを使用せずに同じクエリを実行すると、EntitySecurityKeyフィールドに上記のGUIDが含まれる結果を含め、多くの結果が返されます。guid / binaryフィールドを検索するクエリを作成する別の方法はありますか?

ありがとう!

編集

TOADが醜いブロブではなく文字列を返すのは興味深いことでした。別のエディターを使用して結果を返します(フィルター処理されていないクエリの場合)。生のバイナリデータを取得します。私のクエリはbinaryキーワードを使用して機能すると想定していましたが、次のいずれも機能しませんでした。

SELECT Id, EntitySecurityKey, Type
FROM mydb.security_entityreferences 
where EntitySecurityKey  =  BINARY '02a36462-49b7-406a-a3b6-d5accd6695e5'

SELECT Id, EntitySecurityKey, Type
FROM mydb.security_entityreferences 
where BINARY  EntitySecurityKey  =  '02a36462-49b7-406a-a3b6-d5accd6695e5'
4

6 に答える 6

3

私はRhinoSecurityに精通していませんが、私が知る限り、NHibernateを使用してデータベースに保存します。

.net Guidは、内部で1 Int32、2 Int16、および8バイトを使用して128ビットのGuid値を格納します。NHibernate(3.2)は、BINARY(16)列との間でGuid値を格納/取得するときに、それぞれ.Net ToByteArray()メソッドとGuid(Byte [] ...)コンストラクターを使用します。これらのメソッドは基本的に、バイトの順序をInt32値とInt16値に交換します。メソッドを振り返って正確なコードを確認できますが、最初の4バイトの簡単な例を次に示します。

guidBytes[0] = (byte)this._int32member;
guidBytes[1] = (byte)(this._int32member >> 8), 
guidBytes[2] = (byte)(this._int32member >> 16), 
guidBytes[3] = (byte)(this._int32member >> 24);

これが問題の原因である可能性があります。

たとえば、GUIDはMySqlに別の方法で保存されます。
02a36462-49b7-406a-a3b6-d5accd6695e5- Guid.ToString()からのGUID
6264a302-b749-6a40-a3b6-d5accd6695e5- MySql hex(Guid)を使用したMySqlのGUID
注:hex(x)はダッシュを追加しません。比較のためにダッシュを手動で追加しました。最初の8バイトの順序が異なることに注意してください。

これが問題であるかどうかをテストするには、次のクエリを実行します。

SELECT Id, EntitySecurityKey, Type
FROM mydb.security_entityreferences 
where EntitySecurityKey = UNHEX(REPLACE(6264a302-b749-6a40-a3b6-d5accd6695e5,'-',''));  

もしそうなら、私が自分の旅行で気づいた他のいくつかのアイテム:

Toad for MySqlは、selectステートメントの出力でGuidを.netに相当するものとして表示するため、これも複雑になります。(少なくとも私の経験から)selectのwhere句にそのGuidを含めると、同じ変換は適用されません。MySqlによって保存されたGUIDを使用する必要があります。

DBクエリを実行するときにGuidを手動で変換する必要があるか、Guidを別の方法で変換するためにカスタムNHibernateタイプを導入する必要がある場合があります。

以下を参照できます。

更新: 上記のペーストビンリンクでカスタムNHタイプを試しました。少なくとも私の環境では、バイト順序が正しくありません。私は必要だろう:

private static readonly int[] ByteOrder = new[] { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 };

.Net出力で作成するには、テーブル出力から選択したhex(Guid列)と一致させます。

于 2012-10-15T21:27:44.043 に答える
2

興味深いのは、GUID を16binary(16)に重点を置いたフィールドに格納していることです。マニュアルによると、フィールドの長さはバイト単位であり、それを超えるものはすべて切り捨てられます (厳密モードのみ) GUID が切り詰められている可能性はありますか? サンプル GUID を使用して、最初の 16 文字でデータベースのクエリを実行してみてください。binary02a36462-49b7-406a-a3b6-d5accd6695e5

WHERE EntitySecurityKey = '02a36462-49b7-40'

この質問に対する受け入れられた回答によると、フィールドはchar(16) binary、だけでなく、GUID を格納する必要がありますbinary(16)。ただし、サンプル テーブルではこれを機能させることができませんでした。

私にとってうまくchar(36)いったのは、とを使用していたことbinary(36)です。フィールド長を 16 ではなく 36 に更新してみてください (念のため、最初にテスト テーブルでこれを行います)。

ここに私のテストテーブルがあります:

CREATE TABLE test_security_keys (
    test_key1 char(16) not null,
    test_key2 char(16) binary not null,
    test_key3 char(36) not null,
    test_key4 binary(16) not null,
    test_key5 binary(36) not null
);

次に、多数の GUID (行の各列に同じもの) を挿入するスクリプトを実行しました。サンプル GUID でテストできます。

INSERT INTO test_security_keys
    VALUES ('02a36462-49b7-406a-a3b6-d5accd6695e5', '02a36462-49b7-406a-a3b6-d5accd6695e5', '02a36462-49b7-406a-a3b6-d5accd6695e5', '02a36462-49b7-406a-a3b6-d5accd6695e5', '02a36462-49b7-406a-a3b6-d5accd6695e5');

シンプルを使用すると、切り捨てられるSELECT * FROM test_security_keysサイズの列を除くすべての列が表示されます。36また、binaryまたはそうでない場合でも、通常の文字列比較を使用して列を正常にクエリできました。

SELECT * FROM test_security_keys WHERE test_key3 = '02a36462-49b7-406a-a3b6-d5accd6695e5';
SELECT * FROM test_security_keys WHERE test_key5 = '02a36462-49b7-406a-a3b6-d5accd6695e5';

現在の列が切り捨てられbinary(16) ていないことを確認した場合は、句で a を使用することCAST()をお勧めします。WHERE以下は機能するはずです(サンプルクエリで):

SELECT Id, EntitySecurityKey, Type
FROM mydb.security_entityreferences 
WHERE
    EntitySecurityKey = CAST('02a36462-49b7-406a-a3b6-d5accd6695e5' AS binary(16));

あなたCAST(.. AS binary(16))と入力データが 16 バイトより長い場合、MySQL は警告を発行する必要があります (表示されず、何にも影響しないはずSHOW WARNINGS;です)。binary(16)これは当然のことですが、 を使用して GUID を格納することはできず、binary(36)またはを使用する必要があることも意味しますchar(36)

* を使用してこれを試したことはありませんがTOAD、コマンドラインの MySQLNavicat の両方を使用しましたが、両方で同じ結果が得られました。

于 2012-10-06T19:53:52.607 に答える
1

私が少し修正したあなたの編集から:

してみてください

SELECT Id, EntitySecurityKey, Type
FROM mydb.security_entityreferences
WHERE EntitySecurityKey  = X'02a3646249b7406aa3b6d5accd6695e5'

文字列にはそれぞれ 16 の 16 進数の bye があるため、動作する可能性があります...

于 2012-10-12T18:13:30.357 に答える
0

テーブルで GUID データが実際にどのように見えるかを確認しましたか? これは主キーであるため、GUID 文字列として保存されない可能性が非常に高くなります。その場合、文字列値のクエリは明らかに機能しません。

おそらくそれはバイナリ形式ですか?または、文字列ですが、ハイフンがありませんか? それとも、別の方法で変換されたのでしょうか。あなたのデータを見ないとわかりません。ただし、どのような場合でも、存在することがわかっている GUID がクエリを実行しても見つからない場合は、その GUID がどのような形式であっても、クエリを実行している形式で格納されていないことは明らかです。

これを解決する方法は、存在することがわかっているレコードで別の値を検索することです。または、where句をまったく使用せずに、上位のいくつかのレコードをクエリすることもできます。

これにより、データが実際にどのように見えるかがわかります。運が良ければ、それがどのようにフォーマットされているかを理解するのに十分です。

それでも解決しない場合は、次の質問から手がかりが得られる可能性があります:なぜバイナリ Guid は通常の表現と異なるのか

それが役立つことを願っています。

于 2012-10-06T20:06:02.260 に答える
-1

データベースがどのように設定されているかわかりませんが、次の 2 つのバリアントを試してみます。

SELECT Id, EntitySecurityKey, Type
FROM mydb.security_entityreferences 
where EntitySecurityKey  =  x'02a3646249b7406aa3b6d5accd6695e5'

SELECT Id, EntitySecurityKey, Type
FROM mydb.security_entityreferences 
where EntitySecurityKey  =  x'6264a302b7496a40b6a3d5accd6695e5'
于 2012-10-12T13:07:12.367 に答える