Что такое тип данных SYSNAME в SQL Server?

131

Для чего нужен тип данных SYSNAME SQL Server? BOL говорит:

Тип данных sysname используется для столбцов таблицы, переменных и параметров хранимых процедур, в которых хранятся имена объектов.

но я действительно этого не понимаю. Есть ли вариант использования, который вы можете предоставить?

jrara
источник
1
В дополнение к этим прекрасным ответам, приведенным ниже, он также используется для того, чтобы вызвать хаос для тех, кто пытается получить метаданные столбца с помощью sys.types, потому что он использует тот же system_type_id, что и nvarchar.
StingyJack

Ответы:

150

sysname- это встроенный тип данных, ограниченный 128 символами Unicode, который, IIRC, используется в основном для хранения имен объектов при создании скриптов. Его ценность не может бытьNULL

Это в основном то же самое, что и использование nvarchar(128) NOT NULL

РЕДАКТИРОВАТЬ

Как отметил @Jim в комментариях, я не думаю, что есть действительно бизнес-кейс, который вы бы использовали, sysnameесли честно. Он в основном используется Microsoft при создании внутреннегоsys таблиц, хранимых процедур и т. Д. В SQL Server.

Например, выполнив, Exec sp_help 'sys.tables'вы увидите, что столбец nameопределен так, sysnameпотому что значение this на самом деле является объектом (таблицей).

Я бы слишком беспокоился об этом.

Также стоит отметить, что для тех людей, которые все еще используют SQL Server 6.5 и ниже (есть ли еще люди, использующие его?), Встроенный тип sysnameявляется эквивалентомvarchar(30)

Документация

sysnameопределяется в документации для ncharиnvarchar в разделе примечаний:

sysname - это определяемый системой тип данных, определяемый пользователем, который функционально эквивалентен nvarchar (128) , за исключением того, что он не допускает значения NULL. sysname используется для ссылки на имена объектов базы данных.

Чтобы прояснить приведенные выше замечания, по умолчанию sysname определено, так как NOT NULLего можно определить как допускающее значение NULL. Также важно отметить, что точное определение может варьироваться в зависимости от экземпляра SQL Server.

Использование специальных типов данных

Тип данных sysname используется для столбцов таблицы, переменных и параметров хранимых процедур, в которых хранятся имена объектов. Точное определение sysname связано с правилами для идентификаторов. Следовательно, он может варьироваться в зависимости от экземпляра SQL Server. sysname функционально такое же, как nvarchar (128), за исключением того, что по умолчанию sysname НЕ ПУСТО. В более ранних версиях SQL Server sysname определяется как varchar (30).

Дополнительную информацию о sysnameразрешении или запрещении NULLзначений можно найти здесь https://stackoverflow.com/a/52290792/300863

Тот факт, что это значение по умолчанию (НЕ NULL) не гарантирует, что это будет так!

codingbadger
источник
1
"Есть ли вариант использования, который вы можете предоставить?" Я не думаю, что вы найдете практическую деловую причину для использования. В основном он используется внутри MS SQL, так как он, вероятно, довольно часто используется в таблицах и т. Д.
Джим,
9
Вы можете использовать его sysnameдля прямой (и обратной) совместимости в своих сценариях.
Мартин Смит
просто вставьте здесь 2 цента: столбцы, которые привели меня сюда, объявлены как nvarchar(max)ненулевые в SP, но они отображаются как a sysnameв таблицах sys.
gloomy.penguin
3
@Barry Вообще-то ... в соответствии с sys.typesэтим nvarchar(256) not null. Обратите внимание, что ID системного типа = 231 (nvarchar). В настоящее время он работает как псевдоним типа в TDS; первый идентификатор псевдонима - 256, что соответствует sysname. Что касается использования: sysnameиспользуется в информационных схемах.
atlaste
2
@atlaste Длина max_length в sys.tables указывается в байтах. nvarchar использует два байта на символ, поэтому он определен как nvarchar (128).
Дэвид Раштон,
60

Есть ли вариант использования, который вы можете предоставить?

Если вам когда-либо понадобится создать динамический sql, его можно использовать в sysnameкачестве типа данных для переменных, содержащих имена таблиц, имена столбцов и имена серверов.

Микаэль Эрикссон
источник
6

Просто к вашему сведению ....

select * from sys.types where system_type_id = 231 дает вам две строки.

(я еще не уверен, что это значит, но я на 100% уверен, что прямо сейчас это испортило мой код)

edit: я предполагаю, что это означает, что вы должны присоединиться к user_type_id в этой ситуации (моя ситуация) или, возможно, к user_type_id и th esystem_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
gloomy.penguin
источник
sys.typesсодержит созданные пользователем типы . Если вы это сделаете, у create type MyInt from intвас будет две строки с system_type_id = 56. Другой дублированный по умолчанию - 240, который является системным типом для иерархии, геометрии и географии.
Микаэль Эрикссон,
Я совсем забыл об этом. Итак ... каков идеальный способ запросить этот материал с помощью sysname? так как это «псевдоним», могу я просто сделать, where typ.name<>'sysname'или это будет иметь какие-то другие последствия, о которых я не подозреваю?
gloomy.penguin
3
Присоединитесь к sys.types как для system_type_id, так и для user_type_id. SQL Fiddle
Микаэль Эрикссон
о, вот что я сказал на самом верху. Я думал, ты говоришь, что это неправильно ...
мрачно. Пингвин
Извините за это, я не имел в виду. Просто хотел указать на некоторые другие вещи, которые могут испортить ваш запрос, не только sysname может вызвать у вас горе без объединения в обоих столбцах.
Mikael Eriksson
3

Позвольте мне перечислить ниже вариант использования. Надеюсь, поможет. Здесь я пытаюсь найти владельца таблицы Stud_dtls из БД «Студенты». Как упоминал Микаэль, 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

sysname используется sp_send_dbmail хранимой процедурой, которая «отправляет сообщение электронной почты указанным получателям» и находится в базе данных msdb.

Согласно Microsoft ,

[ @profile_name = ] 'profile_name'  

Имя профиля, из которого отправляется сообщение. Profile_name имеет тип sysname со значением по умолчанию NULL. Profile_name должно быть именем существующего профиля Database Mail. Если имя_профиля не указано, процедура sp_send_dbmail использует частный профиль по умолчанию для текущего пользователя. Если у пользователя нет частного профиля по умолчанию, sp_send_dbmail использует общедоступный профиль по умолчанию для базы данных msdb. Если у пользователя нет частного профиля по умолчанию и нет общедоступного профиля по умолчанию для базы данных, необходимо указать @profile_name.

usefulBee
источник
1

FWIW, вы можете передать имя таблицы таким полезным системным SP, если хотите исследовать базу данных таким образом:

DECLARE @Table sysname; SET @Table = 'TableName';
EXEC sp_fkeys @Table;
EXEC sp_help @Table;
AjV Jsy
источник
0

Другой вариант использования - использование функциональности 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)))

тогда эта переменная должна иметь тип sysname(объявление ее как varcharвызовет ошибку).

d219
источник
0

Есть ли вариант использования, который вы можете предоставить?

Везде, где вы хотите сохранить имя объекта для использования сценариями обслуживания базы данных. Например, сценарий удаляет старые строки из определенных таблиц, в которых есть столбец даты. Он настроен с помощью таблицы, которая дает имя таблицы, имя столбца для фильтрации и сколько дней истории нужно хранить. Другой сценарий выгружает определенные таблицы в файлы CSV и снова настраивается с таблицей, в которой перечислены таблицы для дампа. Эти таблицы конфигурации могут использовать sysnameтип для хранения имен таблиц и столбцов.

Эд Авис
источник
Вам это совсем не нужно. Просто используйте nvarchar(128) not nullстолбец. Имя - это просто имя. Его не обязательно sysnameиспользовать
Панайотис Канавос,
Конечно, и на самом деле он даже не обязательно должен быть такого типа, nvarchar(300)тоже будет работать, или даже varcharесли вы не используете Unicode в именах таблиц (как я уверен, почти никто не делает). Преимущество sysnameотчасти состоит в том, что он проясняет намерение: этот столбец содержит имя объекта; и частично то, что даже если вы перейдете на другую версию MSSQL, которая изменит тип данных, используемый для имен объектов (как это произошло раньше), он останется правильным типом.
Эд Авис,
Нет, это не так. Это просто другой тип пользователя (по сути, псевдоним), которому сопоставлен nvarchar(128) NOT NULL. Фактически, вот как вы можете найти тип - проверив значение user_type_idстолбца. Вы не получите ничего больше, используя этот тип, чем создавая свой собственный тип пользователя.
Панайотис Канавос
Вы имеете в виду, что если определение sysname было изменено в более новой версии MSSQL, а база данных была скопирована и восстановлена ​​в этом более новом экземпляре, все столбцы, которые ранее были sysname, теперь будут иметь неправильный тип и больше не будут соответствовать используемому типу в системных таблицах?
Эд Авис,
Этого не может, или, что еще хуже, если это когда-нибудь случится, ваша колонка будет залита. sysname- это определяемый пользователем тип с usert_type_id256. Нет, ALTER TYPEпоэтому изменить его невозможно. Вам нужно будет создать новый тип и заменить все столбцы, которые использовали старый тип, на новые. Если MS когда-либо решит изменить это, им придется перенести существующие данные системной таблицы в новый тип. Вы можете ожидать, что они сделают это для системных таблиц, о которых они уже знают, но любые пользовательские таблицы должны быть перенесены пользователями
Панайотис Канавос,