Kiểu dữ liệu SYSNAME trong SQL Server là gì?


131

Kiểu dữ liệu SQL Server SYSNAME để làm gì? BOL nói:

Kiểu dữ liệu sysname được sử dụng cho các cột bảng, biến và tham số thủ tục được lưu trữ lưu trữ tên đối tượng.

nhưng tôi không thực sự hiểu điều đó Có một trường hợp sử dụng bạn có thể cung cấp?


1
Ngoài những câu trả lời hay dưới đây, nó cũng được sử dụng để gây ra sự tàn phá cho ai đó đang cố lấy siêu dữ liệu cột bằng sys.types, vì nó chia sẻ cùng system_type_id như nvarchar.
StingyJack

Câu trả lời:


150

sysnamelà một kiểu dữ liệu tích hợp giới hạn ở 128 ký tự Unicode, IIRC, được sử dụng chủ yếu để lưu trữ tên đối tượng khi tạo tập lệnh. Giá trị của nó không thể làNULL

Về cơ bản là giống như sử dụng nvarchar(128) NOT NULL

BIÊN TẬP

Như @Jim đã đề cập trong các bình luận, tôi không nghĩ thực sự có một trường hợp kinh doanh mà bạn sẽ sử dụng sysnameđể trung thực. Nó chủ yếu được Microsoft sử dụng khi xây dựng các sysbảng nội bộ và các thủ tục được lưu trữ, v.v. trong SQL Server.

Ví dụ, bằng cách thực thi, Exec sp_help 'sys.tables'bạn sẽ thấy rằng cột nameđược định nghĩa vì sysnameđây là giá trị của cái này thực sự là một đối tượng trong chính nó (một bảng)

Tôi sẽ lo lắng quá nhiều về nó.

Cũng đáng lưu ý rằng đối với những người vẫn đang sử dụng SQL Server 6.5 trở xuống (vẫn còn người sử dụng nó phải không?) Thì loại tích hợp sysnamelà tương đương vớivarchar(30)

Tài liệu

sysnameđược định nghĩa với tài liệu cho ncharnvarchar , trong phần nhận xét:

sysname là kiểu dữ liệu do người dùng cung cấp do hệ thống cung cấp, có chức năng tương đương với nvarchar (128) , ngoại trừ việc nó không thể rỗng. sysname được sử dụng để tham chiếu tên đối tượng cơ sở dữ liệu.

Để làm rõ các nhận xét trên, theo mặc định sysname được xác định vì NOT NULLchắc chắn có thể định nghĩa nó là nullable. Cũng cần lưu ý rằng định nghĩa chính xác có thể khác nhau giữa các phiên bản của SQL Server.

Sử dụng các loại dữ liệu đặc biệt

Kiểu dữ liệu sysname được sử dụng cho các cột bảng, biến và tham số thủ tục được lưu trữ lưu trữ tên đối tượng. Định nghĩa chính xác của sysname có liên quan đến các quy tắc cho định danh. Do đó, nó có thể khác nhau giữa các phiên bản của SQL Server. sysname có chức năng giống như nvarchar (128) ngoại trừ, theo mặc định, sysname không phải là NULL. Trong các phiên bản trước của SQL Server, sysname được định nghĩa là varchar (30).

Một số thông tin khác về việc sysnamecho phép hoặc không cho phép NULLcác giá trị có thể được tìm thấy ở đây https://stackoverflow.com/a/52290792/300863

Chỉ vì nó là mặc định (KHÔNG phải là NULL) không đảm bảo rằng nó sẽ như vậy!


1
"Có trường hợp sử dụng bạn có thể cung cấp?" Tôi không nghĩ rằng bạn sẽ tìm thấy một lý do kinh doanh thực tế để sử dụng. Chủ yếu là nó được sử dụng nội bộ trong MS SQL vì nó có thể được sử dụng khá nhiều trong các bảng, v.v.
Jim

9
Bạn sẽ sử dụng sysnameđể tương thích (và lùi) trong các tập lệnh của mình.
Martin Smith

chỉ cần đặt 2 xu ở đây: các cột đưa tôi đến đây được tuyên bố là nvarchar(max)không có giá trị trong SP nhưng chúng hiển thị dưới dạng sysnametrong bảng sys.
ảm đạm.penguin 26/03/13

3
@ Thực tế ... theo sys.typesnó a nvarchar(256) not null. Lưu ý rằng loại hệ thống ID = 231 (nvarchar). Nó hoạt động như một bí danh loại trong TDS ngày nay; ID đầu tiên của bí danh là 256, tương ứng với sysname. Đối với việc sử dụng: sysnameđược sử dụng trong lược đồ thông tin.
đúng

2
@atlaste Độ dài max_length tính bằng sys.tables tính bằng byte. nvarchar sử dụng hai byte cho mỗi ký tự, đó là lý do tại sao nó được định nghĩa là nvarchar (128).
David Rushton

60

Có trường hợp sử dụng bạn có thể cung cấp?

Nếu bạn có nhu cầu tạo một số sql động, thì nên sử dụng sysnamelàm kiểu dữ liệu cho các biến chứa tên bảng, tên cột và tên máy chủ.


6

Cũng như một FYI ....

select * from sys.types where system_type_id = 231 cho bạn hai hàng.

(Tôi không chắc điều này có nghĩa là gì nhưng tôi chắc chắn 100% rằng nó đang làm rối mã của tôi ngay bây giờ)

chỉnh sửa: tôi đoán ý nghĩa của việc bạn nên tham gia bởi user_type_id trong tình huống này (tình huống của tôi) hoặc có thể cả user_type_id và 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 

Truy vấn này:

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

sản lượng:

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

và điều này:

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

cung cấp cho bạn điều này:

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.typesgiữ các loại người dùng xác định mà bạn tạo là tốt. Nếu bạn làm create type MyInt from intbạn sẽ có hai hàng với system_type_id = 56. Một cái khác được nhân đôi theo mặc định là 240, đó là loại hệ thống cho phân cấp, hình học và địa lý.
Mikael Eriksson

Tôi hoàn toàn quên về điều đó. Vậy ... cách lý tưởng để truy vấn nội dung này với tên hệ thống trong đó là gì? vì đó là một 'bí danh' tôi chỉ có thể làm where typ.name<>'sysname'hoặc sẽ có một loại hậu quả khác mà tôi không biết?
ảm đạm.penguin 26/03/13

3
Tham gia với sys.types trên cả system_type_id và user_type_id. Fiddle SQL
Mikael Eriksson

oh, đó là những gì tôi đã nói ở trên cùng. Tôi nghĩ bạn đã nói sai ...
ảm đạm.penguin

Xin lỗi về điều đó, không phải ý của tôi. Chỉ muốn chỉ ra một số điều khác có thể gây rối cho truy vấn của bạn, không chỉ tên sys có thể khiến bạn đau buồn mà không tham gia trên cả hai cột.
Mikael Eriksson

3

Hãy để tôi liệt kê một trường hợp sử dụng dưới đây. Hy vọng nó giúp. Ở đây tôi đang cố gắng tìm Chủ sở hữu bảng của Bảng 'Stud_dtls' từ DB 'Học sinh'. Như Mikael đã đề cập, sysname có thể được sử dụng khi có nhu cầu tạo một số sql động cần các biến chứa tên bảng, tên cột và tên máy chủ. Chỉ cần nghĩ đến việc cung cấp một ví dụ đơn giản để bổ sung quan điểm của mình.

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 được sử dụng bởi sp_send_dbmail , một thủ tục được lưu trữ "Gửi tin nhắn e-mail đến người nhận được chỉ định" và được đặt trong cơ sở dữ liệu msdb.

Theo Microsoft ,

[ @profile_name = ] 'profile_name'  

Là tên của hồ sơ để gửi tin nhắn từ. Profile_name có kiểu sysname, với mặc định là NULL. Profile_name phải là tên của hồ sơ cơ sở dữ liệu Mail hiện có. Khi không có profile_name được chỉ định, sp_send_dbmail sử dụng hồ sơ riêng tư mặc định cho người dùng hiện tại. Nếu người dùng không có hồ sơ riêng tư mặc định, sp_send_dbmail sử dụng hồ sơ công khai mặc định cho cơ sở dữ liệu msdb. Nếu người dùng không có hồ sơ riêng tư mặc định và không có hồ sơ công khai mặc định cho cơ sở dữ liệu, @profile_name phải được chỉ định.


1

FWIW, bạn có thể chuyển tên bảng cho SP hệ thống hữu ích như thế này, nếu bạn muốn khám phá cơ sở dữ liệu theo cách đó:

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

0

Một trường hợp sử dụng khác là khi sử dụng chức năng SQL Server 2016+ của AT TIME ZONE

Tuyên bố dưới đây sẽ trả về một ngày được chuyển đổi thành GMT

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

Nếu bạn muốn vượt qua múi giờ dưới dạng một biến, hãy nói:

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

thì biến đó cần phải thuộc kiểu sysname(khai báo nó varcharsẽ gây ra lỗi).


0

Có trường hợp sử dụng bạn có thể cung cấp?

Bất cứ nơi nào bạn muốn lưu trữ một tên đối tượng để sử dụng bởi các kịch bản bảo trì cơ sở dữ liệu. Ví dụ: tập lệnh xóa các hàng cũ từ các bảng nhất định có cột ngày. Nó được cấu hình với một bảng cho biết tên bảng, tên cột để lọc và giữ lại bao nhiêu ngày của lịch sử. Một tập lệnh khác chuyển các bảng nhất định thành các tệp CSV và một lần nữa được định cấu hình với một bảng liệt kê các bảng cần kết xuất. Các bảng cấu hình này có thể sử dụng sysnameloại để lưu trữ tên bảng và cột.


Bạn không cần điều đó cả. Chỉ cần sử dụng một nvarchar(128) not nullcột. Tên chỉ có vậy, một tên. Nó không phải sysnameđược sử dụng
Panagiotis Kanavos

Chắc chắn, và trên thực tế, nó thậm chí không phải là loại đó, nvarchar(300)cũng sẽ hoạt động hoặc thậm chí chỉ varcharkhi bạn không sử dụng Unicode trong tên bảng (vì tôi chắc chắn rằng hầu như không ai làm như vậy). Ưu điểm của sysnamemột phần là nó làm cho ý định rõ ràng hơn: cột này chứa một tên đối tượng; và một phần là ngay cả khi bạn chuyển sang một phiên bản MSSQL khác thay đổi kiểu dữ liệu được sử dụng cho tên đối tượng (như đã xảy ra trước đó), nó sẽ tiếp tục là loại đúng.
Ed Avis

Không, nó không có. Nó chỉ là một loại người dùng khác (về cơ bản là bí danh) được ánh xạ tới nvarchar(128) NOT NULL. Thực tế, đó là cách bạn có thể tìm thấy loại - bằng cách kiểm tra user_type_idgiá trị của cột. Bạn không kiếm được nhiều hơn bằng cách sử dụng loại đó, hơn là bạn sẽ tạo ra loại người dùng của riêng bạn
Panagiotis Kanavos

Bạn có nghĩa là nếu định nghĩa sysnameđã được thay đổi trong phiên bản MSSQL mới hơn và cơ sở dữ liệu được sao lưu và khôi phục vào phiên bản mới hơn đó, thì tất cả các cột trước đây sysnamesẽ thuộc loại sai và không còn phù hợp với loại được sử dụng trong bảng hệ thống?
Ed Avis

Không thể, hoặc tệ hơn, nếu điều đó từng xảy ra, cột của bạn bị hos. sysnamelà loại do người dùng xác định với usert_type_id256. Không ALTER TYPEcó cách nào để thay đổi. Bạn phải tạo một loại mới và thay đổi tất cả các cột đã sử dụng loại cũ thành loại mới. Nếu MS quyết định thay đổi điều này, họ sẽ phải di chuyển dữ liệu bảng hệ thống hiện có sang loại mới. Bạn có thể mong đợi họ làm điều này cho các bảng hệ thống mà họ đã biết, nhưng bất kỳ bảng người dùng nào cũng sẽ phải được người dùng di chuyển
Panagiotis Kanavos
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.