web-dev-qa-db-ja.com

クエリでCOLLATEを使用するためのルールは何ですか?

スクリプトをまとめて、データベースオブジェクトへのアクセス許可を与えます。

SELECT  permission_order=710
       ,permission_type = 'Object Level Permissions'
       ,db = db_name(),
login_=null,
role_=dp.name collate Latin1_General_CI_AS,
Obj = sys.schemas.name + '.' + so.name collate Latin1_General_CI_AS,
Permission = permission_name collate Latin1_General_CI_AS,
[script]=
'IF OBJECT_ID ('  + '''' + '['+ sys.schemas.name + '].[' + so.name + ']'  + '''' + ') IS NOT NULL ' + CHAR(10) + state_desc + 
' ' + permission_name + ' on ['+ sys.schemas.name + '].[' + so.name + '] to [' + dp.name + ']' collate Latin1_General_CI_AS + CHAR(10) +
'ELSE ' + CHAR(10) +
'print ' + '''['+ sys.schemas.name + '].[' + so.name + '] - does not exist'''
+ CHAR(13)

from sys.database_permissions a
INNER JOIN  sys.objects so on a.major_id = so.object_id
INNER JOIN sys.schemas on so.schema_id = sys.schemas.schema_id
INNER JOIN sys.database_principals dp on a.grantee_principal_id = dp.principal_id
WHERE dp.name NOT IN ( 'public', 'guest')
AND a.class = 1

Word collateをできる限り数回使用したいのですが、マルチデータベース、マルチ照合サーバーで実行するスクリプトがまだあります。

どうすればそれを達成できますか? collateを適用するためのルールは何ですか?

enter image description here

5

COLLATEは、コンテキストに応じて述語ごとまたは式ごとを操作します。 COLLATEは主に、文字列値を比較またはソートする方法を制御するために使用されます。したがって、これは、JOINWHEREHAVING述語、およびGROUP BYおよびORDER BY句(この場合、列/式ごとに使用できます)で最も一般的に使用されます。照合順序が異なる可能性のある文字列列に適用する必要があります。非文字列型(XMLを含む)はCOLLATEを使用せず、同じ照合順序を持つことが保証されている列では必要ありません。 JOINWHERE、およびHAVING述語の場合、演算子の片側で指定できるのはneedsだけであり、反対側は指定された照合に強制変換されるためです。

コードページを変更できるため、主にSELECTデータに適用される選択された列/式の照合順序を変更する理由がない限り、それはVARCHARリストで使用されません一般的に私は本当にこの用途のアプリケーションをあまり見ていません。これを行う最も可能性の高い理由は、データを要求するクライアントが別のコードページを必要とする場合ですが、これが必要になる理由は考えられません。

ただし、これをSELECTリスト(およびその他の場所)で使用する理由の1つは、照合が混在する可能性のある2つ以上の列を含む文字列連結を実行するときです。このシナリオは、VARCHARNVARCHARの両方のデータに適用されます。リテラルは列の照合順序に強制されるため、単一の列や文字列リテラルについて心配する必要はありません。

COLLATEリストでSELECTが必要になるもう1つの理由は、UNIONINTERSECT、またはEXCEPTを使用していて、少なくとも2つのクエリ間で同じ位置にある列/式間の照合が同じでない場合です。

したがって、クエリを見てください。

  1. 次の場所ではCOLLATEは必要ありません。
    • role_=dp.name collate Latin1_General_CI_AS,
      単一の列を選択しているだけなので、何も混合されていません。
    • Obj = sys.schemas.name + '.' + so.name collate Latin1_General_CI_AS,
      両方の列は、同じデータベースからのデータベースレベルのメタデータであり、同じ照合順序であることが保証されています。さらに、データベースのデフォルトの照合順序である文字列リテラル(連結されている2つの列と同じ) )、ただし、同じでなくても、2つの列の照合順序に強制変換されます。ここでの唯一の改善点は、リテラルの前に大文字のNを付けることです。これは、式がNVARCHARであるため、NVARCHAR(128)のエイリアスであるsysname型のスキーマ名とオブジェクト名であるためです。
    • Permission = permission_name collate Latin1_General_CI_AS,
      単一の列を選択しているだけなので、何も混合されていません。
  2. データベースレベルのメタデータ(データベースのデフォルトの照合を使用)とシステムレベルのメタデータ(つまり、state_descpermission_name)が混在しているため、文字列連結にCOLLATEが必要do非表示のmssqlsystemresourceデータベースであり、通常はLatin1_General_CI_AS_KS_WSの照合順序があります。 COLLATEは、優先度が最も高く、リテラルと列の両方を指定された照合順序に強制するため、式ごとに1回だけ指定するのが適切です。

最後に、指定するwhich照合順序について:DATABASE_DEFAULTCATALOG_DEFAULT、または選択したいずれか(ここで実行中など):NVARCHARデータで作業している場合(コードページを変更する可能性なし/文字セット)およびCOLLATEをソートまたは比較に使用しない(クエリが異なるデータベース間でどのように機能するかを変更する可能性はありません)、それは本当に重要ではありません。この特定のシナリオではすべて同じです。クエリ(またはその特定の述語またはORDER/GROUPアイテム)をローカルデータベースに依存させ、クエリが実行される場所に応じて動作を変更する必要がある場合は、DATABASE_DEFAULTまたはCATALOG_DEFAULTを使用します。

その他の注意事項:

  1. 結果セットの列名を角かっこで囲むことをお勧めします(つまり、[permission_order]の代わりにpermission_order[role_]の代わりにrole_など)。
  2. 末尾のCHAR(13)は、その連結の残りの改行と同様にCHAR(10)である必要があります。
  3. N/sysname列を連結して文字列全体を強制するので、NCHAR(10)and連結の各文字列リテラル部分に大文字のNVARCHARを前置するのがさらに良いでしょう。 NVARCHAR、したがって、これらのCHAR()参照と文字列リテラルは暗黙的に変換されます。
  4. また、QUOTENAMEには埋め込まれた区切り文字をエスケープする利点があるため、スキーマ/オブジェクト名をQUOTENAME()でラップすること(および文字列リテラルの明示的な区切り文字([および])を削除すること)も有効です。
12
Solomon Rutzky