SQL ServerのSYSNAMEデータ型とは何ですか?


131

SQL ServerのSYSNAMEデータ型は何ですか?BOLさんのコメント

sysnameデータ型は、テーブル名、変数、およびオブジェクト名を格納するストアドプロシージャのパラメーターに使用されます。

しかし、私は本当にそれを理解していません。あなたが提供できるユースケースはありますか?


1
以下のこれらの良い答えに加えて、sys.typesを使用して列メタデータを取得しようとする人に大混乱を引き起こすためにも使用されます。これは、nvarcharと同じsystem_type_idを共有するためです。
StingyJack 2018

回答:


150

sysnameIIRCは、スクリプトを作成するときに主にオブジェクト名を格納するために使用される128のUnicode文字に制限された組み込みデータ型です。その値はNULL

基本的には使用と同じです nvarchar(128) NOT NULL

編集

@Jimのコメントで述べたようsysnameに、正直に言うビジネスケースは本当にないと思います。それは主に内部を構築するときにマイクロソフトによって使用されますsys SQL Server内でテーブルやストアドプロシージャなどをます。

たとえば、実行Exec sp_help 'sys.tables'すると、列namesysnameこのように定義されていることがわかります。これは、この値が実際にはオブジェクト自体(テーブル)であるためです。

心配しすぎます。

また、SQL Server 6.5以下をまだ使用している人(まだ使用している人はいますか?)の組み込み型sysnameは、varchar(30)

ドキュメンテーション

sysnameドキュメントで定義されているncharnvarchar、発言のセクションで:

sysname はシステムで提供されるユーザー定義のデータ型であり、nvarchar(128)と機能的に同等ですが、nullにすることはできません。sysnameは、データベースオブジェクト名を参照するために使用されます。

上記の説明を明確にするために、デフォルトでは sysnameが定義されNOT NULLています。また、正確な定義はSQL Serverのインスタンス間で異なる可能性があることに注意することも重要です。

特別なデータ型の使用

システム名のデータ・タイプは、表の列、変数、およびストアドプロシージャのパラメータストアオブジェクト名そのために使用されます。sysnameの正確な定義は 、識別子の規則に関連しています。したがって、SQL Serverのインスタンス間で異なる可能性があります。sysnameは、デフォルトではsysnameがNOT NULLであることを除いて、nvarchar(128)と機能的に同じです。以前のバージョンのSQL Serverでは、sysnameはvarchar(30)として定義されていました。

値のsysname許可または禁止の詳細については、https://stackoverflow.com/a/52290792/300863をNULL参照してください。

これがデフォルトであること(NOT NULLであること)は、そのことを保証するものではありません。


1
「提供できるユースケースはありますか?」実用的なビジネス上の理由はないと思います。それはおそらくなど、テーブルにかなり使用されているよう大抵それはMS SQLで内部的に使用される
ジム・

9
sysnameスクリプトの前方(および後方)互換性のために使用します。
マーティン・スミス

ここに2セントを入れるだけです。私をここに連れてきた列nvarchar(max)は、SPではnullでないと宣言されていますsysnameが、sysテーブルではaとして表示されています。
gloomy.penguin 2013年

3
@Barry実は...によるとsys.types、それはですnvarchar(256) not null。システムタイプID = 231(nvarchar)であることに注意してください。今日ではTDSの型エイリアスとして機能します。エイリアスの最初のIDは256で、これはに対応しsysnameます。使用法についてsysnameは、情報スキーマで使用されます。
atlaste 2014年

2
@atlaste sys.tablesのmax_lengthの長さはバイト単位です。nvarcharは文字ごとに2バイトを使用するため、nvarchar(128)として定義されています。
David Rushton、2016年

60

提供できるユースケースはありますか?

動的SQLを作成する必要がある場合は、sysnameテーブル名、列名、サーバー名を保持する変数のデータ型として使用するのが適切です。


6

参考までに...

select * from sys.types where system_type_id = 231 2行が表示されます。

(これが何を意味するのかはまだわかりませんが、今はコードがめちゃくちゃになっていると100%確信しています)

編集:私が意味するところは、この状況(私の状況)またはuser_type_idとth esystem_type_idの両方でuser_type_idで参加する必要があるということです

name        system_type_id   user_type_id   schema_id   principal_id    max_length  precision   scale   collation_name                  is_nullable     is_user_defined     is_assembly_type    default_object_id   rule_object_id
nvarchar    231              231            4           NULL            8000        0           0       SQL_Latin1_General_CP1_CI_AS    1               0                   0                   0                   0
sysname     231              256            4           NULL            256         0           0       SQL_Latin1_General_CP1_CI_AS    0               0                   0                   0                   0

create procedure dbo.yyy_test (
    @col_one    nvarchar(max),
    @col_two    nvarchar(max)  = 'default',
    @col_three  nvarchar(1),
    @col_four   nvarchar(1)    = 'default',
    @col_five   nvarchar(128),
    @col_six    nvarchar(128)  = 'default',
    @col_seven  sysname  
)
as begin 

    select 1
end 

このクエリ:

select  parm.name AS Parameter,    
        parm.max_length, 
        parm.parameter_id 

from    sys.procedures sp

        join sys.parameters parm ON sp.object_id = parm.object_id 

where   sp.name = 'yyy_test'

order   by parm.parameter_id

収量:

parameter           max_length  parameter_id
@col_one            -1          1
@col_two            -1          2
@col_three           2          3
@col_four            2          4
@col_five            256        5
@col_six             256        6
@col_seven           256        7

この:

select  parm.name as parameter,    
        parm.max_length, 
        parm.parameter_id,
        typ.name as data_type, 
        typ.system_type_id, 
        typ.user_type_id,
        typ.collation_name,
        typ.is_nullable 
from    sys.procedures sp

        join sys.parameters parm ON sp.object_id = parm.object_id

        join sys.types typ ON parm.system_type_id = typ.system_type_id

where   sp.name = 'yyy_test'

order   by parm.parameter_id

これを与える:

parameter   max_length  parameter_id    data_type   system_type_id  user_type_id    collation_name                  is_nullable
@col_one    -1          1               nvarchar    231             231             SQL_Latin1_General_CP1_CI_AS    1
@col_one    -1          1               sysname     231             256             SQL_Latin1_General_CP1_CI_AS    0
@col_two    -1          2               nvarchar    231             231             SQL_Latin1_General_CP1_CI_AS    1
@col_two    -1          2               sysname     231             256             SQL_Latin1_General_CP1_CI_AS    0
@col_three   2          3               nvarchar    231             231             SQL_Latin1_General_CP1_CI_AS    1
@col_three   2          3               sysname     231             256             SQL_Latin1_General_CP1_CI_AS    0
@col_four    2          4               nvarchar    231             231             SQL_Latin1_General_CP1_CI_AS    1
@col_four    2          4               sysname     231             256             SQL_Latin1_General_CP1_CI_AS    0
@col_five    256        5               nvarchar    231             231             SQL_Latin1_General_CP1_CI_AS    1
@col_five    256        5               sysname     231             256             SQL_Latin1_General_CP1_CI_AS    0
@col_six     256        6               nvarchar    231             231             SQL_Latin1_General_CP1_CI_AS    1
@col_six     256        6               sysname     231             256             SQL_Latin1_General_CP1_CI_AS    0
@col_seven   256        7               nvarchar    231             231             SQL_Latin1_General_CP1_CI_AS    1
@col_seven   256        7               sysname     231             256             SQL_Latin1_General_CP1_CI_AS    0

sys.types同様に作成するユーザー定義型を保持します。あなたが行う場合はcreate type MyInt from int、あなたが持つ2つの行を持つことになりますsystem_type_id = 56。デフォルトで複製されるもう1つは240です。これは、hierarchyid、geometry、geographyのシステムタイプです。
ミカエルエリクソン2013年

そのことはすっかり忘れていました。では、sysnameを使用してこの項目を照会する理想的な方法は何ですか?それは「エイリアス」なので、私はただ行うことができwhere typ.name<>'sysname'ますか、それとも私が知らない他の種類の結果をもたらすでしょうか?
gloomy.penguin 2013年

3
system_type_idとuser_type_idの両方でsys.typesに対して結合します。SQLフィドル
ミカエルエリクソン

ああ、それは私が一番上で言ったことです。私はあなたがそれが間違っていると言っていたと思った...
憂鬱なペンギン

申し訳ありませんが、私の意味ではありません。クエリをめちゃくちゃにする可能性のある他のいくつかのことを指摘したかっただけですが、sysnameだけでは両方の列を結合せずに悲しみを引き起こす可能性があります。
ミカエルエリクソン2013年

3

以下にユースケースをリストアップします。それが役に立てば幸い。ここでは、DB 'Students'からテーブル 'Stud_dtls'のテーブル所有者を見つけようとしています。Mikaelが述べたように、sysnameは、テーブル名、列名、サーバー名を保持する変数を必要とする動的SQLを作成する必要がある場合に使用できます。彼のポイントを補足する簡単な例を提供することを考えただけです。

USE Students

DECLARE @TABLE_NAME sysname

SELECT @TABLE_NAME = 'Stud_dtls'

SELECT TABLE_SCHEMA 
  FROM INFORMATION_SCHEMA.Tables
 WHERE TABLE_NAME = @TABLE_NAME

2

sysnamesp_send_dbmail、「指定された受信者に電子メールメッセージを送信する」ストアドプロシージャによって使用され、msdbデータベースにあります。

マイクロソフトによると、

[ @profile_name = ] 'profile_name'  

メッセージの送信元のプロファイルの名前です。profile_nameのタイプはsysnameであり、デフォルトはNULLです。profile_nameは、既存のデータベースメールプロファイルの名前である必要があります。profile_nameが指定されていない場合、sp_send_dbmailは現在のユーザーのデフォルトのプライベートプロファイルを使用します。ユーザーに既定のプライベートプロファイルがない場合、sp_send_dbmailはmsdbデータベースの既定のパブリックプロファイルを使用します。ユーザーにデフォルトのプライベートプロファイルがなく、データベースのデフォルトのパブリックプロファイルがない場合は、@ profile_nameを指定する必要があります。


1

FWIW、データベースをそのように探索したい場合は、次のような便利なシステムSPにテーブル名を渡すことができます。

DECLARE @Table sysname; SET @Table = 'TableName';
EXEC sp_fkeys @Table;
EXEC sp_help @Table;

0

もう1つの使用例は、SQL Server 2016以降の機能を使用する場合です。 AT TIME ZONE

以下のステートメントは、GMTに変換された日付を返します

SELECT 
CONVERT(DATETIME, SWITCHOFFSET([ColumnA], DATEPART(TZOFFSET, [ColumnA] AT TIME ZONE 'GMT Standard Time')))

タイムゾーンを変数として渡したい場合は、次のようにします。

SELECT 
CONVERT(DATETIME, SWITCHOFFSET([ColumnA], DATEPART(TZOFFSET, [ColumnA] AT TIME ZONE @TimeZone)))

その場合、その変数は型である必要がありますsysnamevarcharエラーを引き起こすと宣言する)。


0

提供できるユースケースはありますか?

データベースメンテナンススクリプトで使用するオブジェクト名を保存する場所。たとえば、スクリプトは日付列がある特定のテーブルから古い行を削除します。これは、テーブル名、フィルタリングする列名、および何日分の履歴を保持するかを指定するテーブルで構成されています。別のスクリプトは、特定のテーブルをCSVファイルにダンプし、再び、ダンプするテーブルをリストするテーブルで構成されます。これらの構成テーブルは、sysnameタイプを使用してテーブルと列の名前を格納できます。


それはまったく必要ありません。nvarchar(128) not nullカラムを使用するだけです。名前はまさにそれ、名前です。sysname使用する必要はありません
Panagiotis Kanavos

確かに、実際にそれも、そのタイプである必要はありませんnvarchar(300)あまりにも、あるいは動作しますvarchar(私は確信してほとんど誰もしませんよと)あなたは、テーブル名にUnicodeを使用しない場合。の利点の1つsysnameは、意図がより明確になることです。この列にはオブジェクト名が保持されます。一部は、オブジェクト名に使用されるデータ型を変更する別のバージョンのMSSQLに移行しても(以前のように)、引き続き正しい型であることに注意してください。
Ed Avis

いいえ、ありません。これは、にマップされた別のユーザータイプ(本質的にはエイリアス)にすぎませんnvarchar(128) NOT NULL。実際、user_type_id列の値を確認することで、それがタイプを見つける方法です。独自のユーザータイプを作成するよりも、そのタイプを使用しても何も得られません
Panagiotis Kanavos

の定義がsysname新しいMSSQLバージョンで変更され、データベースがバックアップされ、その新しいインスタンスに復元された場合、以前に使用されていたすべての列がsysname誤ったタイプになり、使用されたタイプと一致しなくなるということですか?システムテーブル内?
Ed Avis

それができない場合、またはさらに悪いことに、それが発生した場合、カラムがホース接続されます。256のsysnameユーザー定義型です。存在しusert_type_idないALTER TYPEため、変更する方法はありません。新しいタイプを作成し、古いタイプを使用していたすべての列を新しいタイプに変更する必要があります。MSはこれまで、これを変更することを決めた場合、彼らはと思い、新しいタイプに既存のシステム・テーブル・データを移行する必要があります。彼らがすでに知っているシステムテーブルに対してこれを行うことを期待できますが、ユーザーテーブルはユーザーが移行する必要があります
Panagiotis Kanavos
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.