Một chuỗi là một chuỗi, amirite?
Có và Không: một chuỗi là một chuỗi, nhưng tên đối tượng / mục không phải là chuỗi. Vì vậy, trong khi tuyên bố đó là đúng, nó cũng không liên quan đến hành vi mà bạn đang thấy.
Bỏ qua lý do khái niệm cho các quy tắc cụ thể, câu trả lời kỹ thuật cho "tại sao cái này hoạt động mà không phải cái kia" là SQL Server tuân theo (với tùy chỉnh tối thiểu), hướng dẫn của Unicode Standard cho các định danh. Tài liệu Unicode có thể được tìm thấy ở đây:
Phụ lục tiêu chuẩn Unicode® # 31: UNICODE IDENTIFIER VÀ THỰC HIỆN TỔNG HỢP
Các định danh không được đặt trong một trong hai [...]
hoặc "..."
là các định danh "thông thường", trong khi các định danh được bao quanh là các định danh "được phân cách". Mã định danh thông thường là tên hợp lệ trong tất cả các ngữ cảnh (nghĩa là đây là các quy tắc để đặt tên các thứ trong ngôn ngữ này, phần mềm, v.v.). Các định danh được phân tách là mọi thứ khác: các tên không hợp lệ và không hoạt động, tuy nhiên, chúng sẽ được miễn nếu bạn bọc chúng trong một trong các dấu phân cách đó. Hầu hết các định danh có thể được phân định; nó chỉ làGOTO
nhãn và biến (bao gồm cả biến bảng) / tham số không thể phân định. Sự khác biệt dường như là các mã định danh tồn tại hoàn toàn để sử dụng trong ngôn ngữ T-SQL (nghĩa là không phải là tên sẽ được lưu trữ trong tệp dữ liệu hoặc tệp nhật ký dưới dạng dữ liệu meta) không thể được phân định (nhiều như bạn mong đợi bất kỳ ngôn ngữ nào).
Bây giờ, tài liệu SQL Server không hoàn toàn chính xác / chính xác, nhưng nó chính xác về việc phân loại ký tự "định danh" hợp lệ (cả bắt đầu và tiếp tục) đến từ Unicode 3.2. Nếu bạn muốn danh sách quy tắc thực tế cho cả số nhận dạng thông thường và phân định, tôi đã ghi lại chúng ở đây:
Danh sách quy tắc hoàn chỉnh cho mã định danh T-SQL
Để xem nghiên cứu chứng minh mối quan hệ giữa các phân loại Unicode 3.2 và những gì SQL Server chấp nhận cho các định danh thông thường, vui lòng truy cập:
- Uni-Code: Tìm kiếm danh sách các ký tự hợp lệ cho mã định danh thông thường T-SQL, Phần 1
- Uni-Code: Tìm kiếm danh sách các ký tự hợp lệ cho mã định danh thông thường T-SQL, Phần 2
Giải quyết các mối quan tâm được ghi nhận trong các ý kiến về câu trả lời này:
- Vâng, thậm chí cho phép định danh không được phân định để bắt đầu với
_
, #
và @
được hạch toán vào spec Unicode. Mục 1.2 địa chỉ tùy chỉnh các quy tắc cơ bản, và thậm chí cung cấp bốn tùy chỉnh ví dụ: _
, #
, @
, và $
. 4 tùy chỉnh "tiềm năng" đó là 4 chính xác mà SQL Server sử dụng. Do đó, SQL Server cho phép @Variable
và #TempTable
không không chỉ đi từ tài liệu Unicode này như là nguồn gốc của các quy tắc.
- Như đã lưu ý ở trên, tài liệu SQL Server nêu rõ rằng các phân loại được sử dụng là từ phiên bản 3.2 của Cơ sở dữ liệu ký tự Unicode và chúng hiện đang ở phiên bản 10. Bạn không thể sử dụng các định nghĩa hiện tại của Ident_ * , như được tìm thấy trên trang web Unicode, như chỉ ra các ký tự hợp lệ / không hợp lệ. Các ký tự được thêm vào
Ident_Start
và Ident_Continue
trong mỗi phiên bản mới của Tiêu chuẩn Unicode. Cách duy nhất để xem bộ ký tự chính xác khớp với các thuộc tính này là tải xuống Unicode Phiên bản 3.2.
- Cả hai điểm trên đều được xử lý trong hai bài đăng trên blog được ghi chú trực tiếp ở trên (có tên là "The Uni-Code: The Search for True List of Ký tự hợp lệ cho số nhận dạng thông thường T-SQL"). Xin vui lòng đọc hai bài viết trước khi bỏ qua câu trả lời này là không chính xác. Có rất nhiều sắc thái đằng sau những gì thực sự đang diễn ra ở đây mà tôi đề cập đến trong hai bài đăng đó, chỉ ra từng bước làm thế nào để phù hợp với danh sách các ký tự hợp lệ.
CSONG, liên quan đến câu hỏi như được nêu trong tiêu đề, nó phụ thuộc vào cách bạn xác định "số" một cách lỏng lẻo. Có nghĩa là, nếu bạn làm theo các bước nghiên cứu như trong hai bài đăng được ghi chú trực tiếp ở trên, như vậy bạn đã tạo một bảng để chứa Cơ sở dữ liệu Ký tự Unicode v3.2 và một vài thuộc tính bổ sung, bạn có thể nhận được danh sách 52 không -letters (chủ yếu là "số") là các ký tự hợp lệ để bắt đầu một định danh thông qua truy vấn sau:
SELECT ucd.*
FROM [v3-2].UnicodeCharacterDatabase ucd
WHERE ucd.[IDStart] = 1
AND ucd.[GeneralCategory] NOT LIKE 'L%';
Chọn một vài trong số các nhân vật đó để kiểm tra, chúng ta có thể thấy rằng họ thực sự làm việc:
USE [tempdb];
CREATE TABLE dbo.Ⅳaii ([Col1] INT); -- ROMAN NUMERAL FOUR (U+2163)
CREATE TABLE dbo.ↂaii ([Col1] INT); -- ROMAN NUMERAL TEN THOUSAND (U+2182)
CREATE TABLE dbo.〤aii ([Col1] INT); -- HANGZHOU NUMERAL FOUR (U+3024)
Và, chỉ để cho thấy rằng chúng là "số" không chỉ là tên của chúng, truy vấn sau đây chứng minh rằng chúng được gán một giá trị số (như được hiển thị trong NumericValue
cột của [v3-2].UnicodeCharacterDatabase
bảng:
SELECT 1 WHERE N'〤' LIKE N'[3-5]'; -- HANGZHOU NUMERAL FOUR (U+3024)
-- 1
Tuy nhiên, chúng không phải là số có thể được sử dụng trong các hoạt động số:
SELECT 〤 + 0;
/*
Msg 207, Level 16, State 1, Line 23
Invalid column name '〤'.
*/
Liên quan đến vấn đề phân tích cú pháp và cần có khả năng xác định xem đó 3e2
là số hay số nhận dạng: trong khi đây là một sự cân nhắc và có thể tại sao các số được loại trừ khỏi danh mục chung Unicode "Nhận dạng", nó không phải là phổ biến và không nhất thiết là tại sao Máy chủ SQL loại trừ chúng. Ba điểm cần xem xét:
- Mặc dù
3e2
bản thân nó không rõ ràng, nhưng nếu nó đủ điều kiện có ít nhất một tên lược đồ thì nó sẽ không:dbo.3e2
- Cái tên
4aii
không thực sự mơ hồ chút nào. Phân tích cú pháp nội bộ sẽ có thể xác định đủ dễ dàng như không phải là một số tiềm năng
MySQL / MariaDB làm không có hạn chế này. Chúng cho phép các định danh không phân cách như 4aii
và 3e
, nhưng không 3e2
hoặc 300
. Tôi đã có thể thực hiện thành công những điều sau trong MySQL:
create table 4aii (3e int);
Vì vậy, một lần nữa, lý do mà bạn không thể làm điều này trong SQL Server là vì SQL Server tuân thủ khuyến nghị của Tiêu chuẩn Unicode cho các định danh. Tại sao những ký tự đó được chọn bởi Hiệp hội Unicode không được nêu cụ thể, nhưng dường như ít nhất là "thực tiễn tốt nhất". Tuy nhiên, như đã được chứng minh với MySQL, có thể phân tích các định danh bắt đầu bằng một số.