Що таке тип даних SYSNAME у SQL сервері?


131

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

Тип даних sysname використовується для стовпців таблиць, змінних та збережених параметрів процедури, що зберігають імена об'єктів.

але я насправді цього не розумію. Чи можете ви надати футляр для використання?


1
На додаток до цих чітких відповідей, наведених нижче, він також використовує для заподіяння шкоди для тих, хто намагається отримати метадані стовпців за допомогою sys.types, оскільки він має той самий system_type_id, як nvarchar.
StingyJack

Відповіді:


150

sysnameце вбудований тип даних, обмежений 128 символами Unicode, який, IIRC, використовується в основному для зберігання імен об'єктів при створенні сценаріїв. Його значення не може бутиNULL

Це в основному те саме, що використовувати nvarchar(128) NOT NULL

EDIT

Як згадував @Jim у коментарях, я не думаю, що насправді є діловий випадок, коли ви використовували sysnameб чесно. Він в основному використовується Microsoft при побудові внутрішніх sysтаблиць і збережених процедур тощо в SQL Server.

Наприклад, виконавши Exec sp_help 'sys.tables'ви побачите, що стовпець nameвизначається так sysname, оскільки це значення насправді є об'єктом сам по собі (таблиця)

Я б надто переживав про це.

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

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

sysnameвизначається з документацією для ncharтаnvarchar в розділі зауважень:

sysname - це системний тип даних, визначений користувачем, який функціонально еквівалентний nvarchar (128) , за винятком того, що він не зводиться до нуля. sysname використовується для посилання на імена об'єктів бази даних.

Для уточнення вищезазначених зауважень, за замовчуванням sysname визначається, оскільки NOT NULLце, безумовно, можна визначити як нульове. Важливо також зазначити, що точне визначення може змінюватись між екземплярами SQL Server.

Використання спеціальних типів даних

SYSNAME тип даних використовується для стовпців таблиці, змінних і параметрів збережених процедур , що імена об'єктів магазин. Точне визначення sysname пов'язане з правилами для ідентифікаторів. Отже, він може відрізнятися між примірниками SQL Server. sysname функціонально такий же, як nvarchar (128), за винятком того, що за замовчуванням sysname НЕ NULL. У більш ранніх версіях SQL Server sysname визначається як varchar (30).

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

Просто тому, що це за замовчуванням (бути НЕ NULL) не гарантує, що воно буде!


1
"Чи є випадок використання, який ви можете надати?" Я не думаю, що ви знайдете практичну ділову причину для використання. Здебільшого він використовується внутрішньо в MS SQL, оскільки він, ймовірно, використовується зовсім небагато у таблицях тощо.
Джим

9
Ви б використовували sysnameдля прямої (і назад) сумісності у своїх сценаріях.
Мартін Сміт

просто вводячи тут 2 центи: стовпці, які привели мене сюди, nvarchar(max)у SP відображаються як недійсні, але вони відображаються як sysnameтаблиці в sys.
похмурий.penguin

3
@Barry Насправді ... відповідно до sys.typesцього nvarchar(256) not null. Зверніть увагу, що тип системи ID = 231 (nvarchar). Він працює як псевдонім типу в TDS сьогодні; перший ідентифікатор псевдоніма - 256, що відповідає sysname. Що стосується використання: sysnameвикористовується в інформаційних схемах.
atlaste

2
@atlaste Максимальна довжина довжини в sys.tables знаходиться в байтах. nvarchar використовує два байти на символ, тому його визначають як nvarchar (128).
Девід Раштон

60

Чи є виправданий випадок, який ви можете надати?

Якщо у вас виникне потреба у створенні динамічного sql , доречно використовувати sysnameяк тип даних для змінних, що містять назви таблиць, назви стовпців та імена серверів.


6

Так само, як вигадка ....

select * from sys.types where system_type_id = 231 дає два ряди.

(я не впевнений, що це означає, але я на 100% впевнений, що зараз зіпсує свій код)

редагувати: я здогадуюсь, що це означає, що ви маєте приєднатися до користувача user_type_id у цій ситуації (моя ситуація) або, можливо, як user_type_id, так і 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

sys.typesмістить також визначені користувачем типи, які ви також створюєте. Якщо у вас, у create type MyInt from intвас буде два ряди system_type_id = 56. Інший, який дублюється за замовчуванням, це 240, який є системним типом для ієрархії, геометрії та географії.
Мікаель Ерікссон

Я про це повністю забув. Отже ... що є ідеальним способом запиту цього матеріалу з ім'ям sysname там? оскільки це "псевдонім", чи можу я це зробити, where typ.name<>'sysname'чи це може спричинити якісь інші наслідки, про які я не знаю?
похмурий.penguin

3
Приєднуйтесь до sys.types як на system_type_id, так і на user_type_id. SQL Fiddle
Mikael Eriksson

о, це я сказав на самому верху. Я думав, ти говориш, що це було неправильно ...
gloomy.penguin

Вибачте з цього приводу, не моє значення. Просто хотілося вказати на деякі інші речі, які можуть зіпсувати ваш запит, не тільки sysname може викликати у вас горе, не приєднуючись до обох стовпців.
Мікаель Ерікссон

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'  

Це ім'я профілю, з якого слід надсилати повідомлення. Ім'я профілю_системи типу sysname, за замовчуванням NULL. Ім'я профілю має бути ім'ям існуючого профілю пошти бази даних. Якщо не вказано ім'я профілю, 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

Інший випадок використання - це при використанні функціональності 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, що спричинить помилку).


0

Чи є виправданий випадок, який ви можете надати?

Куди ви хочете зберегти ім'я об'єкта для використання сценаріями обслуговування бази даних. Наприклад, сценарій очищає старі рядки з певних таблиць, у яких стовпець дати. Він налаштований з таблицею, яка дає ім’я таблиці, ім'я стовпця для фільтрації та кількість днів історії для збереження. Інший скрипт скидає певні таблиці до файлів CSV, і знову налаштовується на таблицю, в якій перераховані таблиці для скидання. Ці таблиці конфігурації можуть використовувати sysnameтип для зберігання імен таблиць і стовпців.


Вам це зовсім не потрібно. Просто використовуйте nvarchar(128) not nullстовпчик. Ім'я саме це, ім'я. Його не sysnameпотрібно використовувати
Panagiotis Kanavos

Звичайно, і насправді це навіть не повинно бути такого типу, nvarchar(300)це працювало б надто і навіть просто, varcharякщо ви не використовуєте Unicode в назвах таблиць (як я впевнений, майже ніхто не робить). Перевага sysnameчастково полягає в тому, що він робить наміри зрозумілішими: цей стовпець містить ім'я об'єкта; і частково, що навіть якщо ви перейдете до іншої версії MSSQL, яка змінює тип даних, який використовується для імен об'єктів (як це було раніше), він буде продовжувати бути правильним типом.
Ед Авіс

Ні, це не так. Це просто інший тип користувача (по суті псевдонім), відображений у nvarchar(128) NOT NULL. Насправді саме так можна знайти тип - перевіривши значення user_type_idстовпця. Використовуючи цей тип, ви нічого не отримуєте , ніж ви створили власний тип користувача
Panagiotis Kanavos

Ви маєте на увазі, що якби визначення sysnameбуло змінено в більш новій версії MSSQL, а база даних була резервна копія та відновлена ​​в той новіший екземпляр, усі стовпці, які раніше були, були sysnameб неправильного типу і більше не відповідатимуть використаному типу в системних таблицях?
Ед Авіс

Не може, або ще гірше, якщо це коли-небудь трапиться, ваш стовпчик шлангується. sysnameце визначений користувачем тип з usert_type_id256. Немає ALTER TYPEможливості змінити його. Вам доведеться створити новий тип і змінити всі стовпці, які використовували старий тип, на новий. Якщо MS коли-небудь вирішить змінити це, їм доведеться перенести існуючі дані системної таблиці до нового типу. Ви можете очікувати, що вони це зроблять для системних таблиць, про які вони вже знають, але будь-які таблиці користувачів повинні бути переміщені користувачами
Panagiotis Kanavos
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.