In-Memory OLTP 對記憶體優化資料表中的 (var)char 欄位所支援的字元頁面以及在索引和原生編譯預存程序中使用的支援排序規則有限制。
(var)char 值的代碼頁會決定字元與儲存在數據表中的位元組表示法之間的對應。 例如,使用 Windows Latin 1 代碼頁 (1252;SQL Server 預設值),'a' 字元會對應至位元組0x61。
(var)char 值的代碼頁是由與值相關聯的定序所決定。 例如,排序規則 SQL_Latin1_General_CP1_CI_AS 具有相關聯的編碼頁 1252。
值的定序繼承自資料庫定序,或者可以使用 COLLATE 關鍵詞明確指定。 如果資料庫包含記憶體優化數據表或原生編譯預存程式,則無法變更資料庫定序。 下列範例會設定資料庫定序,並建立具有不同定序之數據行的數據表。 資料庫使用拉丁文不區分大小寫的定序。
只有在使用 BIN2 定序時,才能在字串數據行上建立索引。 LastName 變數會使用 BIN2 定序。 FirstName 會使用資料庫的預設值,這是 CI_AS(不區分大小寫、區分重音)。
這很重要
您無法在不使用 BIN2 定序的索引字串資料行上使用 order by 或 group by。
CREATE DATABASE IMOLTP
ALTER DATABASE IMOLTP ADD FILEGROUP IMOLTP_mod CONTAINS MEMORY_OPTIMIZED_DATA
ALTER DATABASE IMOLTP ADD FILE( NAME = 'IMOLTP_mod' , FILENAME = 'c:\data\IMOLTP_mod') TO FILEGROUP IMOLTP_mod;
--GO
-- set the database collations
ALTER DATABASE IMOLTP COLLATE Latin1_General_100_CI_AS
GO
--
USE IMOLTP
GO
-- create a table with collation
CREATE TABLE Employees (
EmployeeID int NOT NULL ,
LastName nvarchar(20) COLLATE Latin1_General_100_BIN2 NOT NULL INDEX IX_LastName NONCLUSTERED,
FirstName nvarchar(10) NOT NULL ,
CONSTRAINT PK_Employees PRIMARY KEY NONCLUSTERED HASH(EmployeeID) WITH (BUCKET_COUNT=1024)
) WITH (MEMORY_OPTIMIZED=ON, DURABILITY=SCHEMA_AND_DATA)
GO
下列限制適用於記憶體優化數據表和原生編譯預存程式:
記憶體優化數據表中的 var)char 數據行必須使用代碼頁 1252 定序。 這項限制不適用於 n(var)char 數據行。 下列程式碼會擷取所有 1252 排序規則:
-- all supported collations for (var)char columns in memory-optimized tables select * from sys.fn_helpcollations() where collationproperty(name, 'codepage') = 1252;如果您需要儲存非拉丁字元,請使用 n(var)char 數據行。
(n)(var)char 數據行上的索引只能以 BIN2 定序指定(請參閱第一個範例)。 下列查詢會擷取所有支援的 BIN2 定序:
-- all supported collations for indexes on memory-optimized tables and -- comparison/sorting in natively compiled stored procedures select * from sys.fn_helpcollations() where name like '%BIN2'如果您透過解譯的 Transact-SQL 存取資料表,您可以使用
COLLATE關鍵字來透過表達式或排序作業調整定序。 如需此範例,請參閱最後一個範例。如果資料庫定序不是代碼頁 1252 定序,原生編譯預存程式就無法使用 (var)char 類型的參數、局部變數或字串常數。
原生編譯預存程式內的所有表達式和排序作業都必須使用 BIN2 定序。 隱含的是,所有比較和排序作業都是以字元的 Unicode 字碼點 (二進位表示法) 為基礎。 例如,所有排序都會區分大小寫('Z' 在 'a' 之前)。 如有必要,請使用解譯 Transact-SQL 進行不區分大小寫的排序和比較。
原生編譯預存程式內不支援截斷 UTF-16 數據。 這表示如果定序具有 _SC 屬性,則 n(var)char(n) 值無法轉換成類型 n(var)char(i),如果 i<n。 例如,不支援下列專案:
-- column definition using an _SC collation c2 nvarchar(200) collate Latin1_General_100_CS_AS_SC not null -- assignment to a smaller variable, requiring truncation declare @c2 nvarchar(100) = ''; select @c2 = c2原生編譯預存程式不支援字串作函式,例如 LEN、SUBSTRING、LTRIM 和具有 UTF-16 數據的 RTRIM。 您無法針對具有_SC定序的 n(var)char 值使用這些字串操作函數。
使用夠大的類型宣告變數,以避免截斷。
下列範例顯示 In-Memory OLTP 中定序限制的一些含意和因應措施。 此範例會使用上面指定的 Employees 數據表。 這個範例會列出所有員工 。 請注意,針對 LastName,由於二進制排列方式,按照大寫名稱會先於小寫名稱排序。 因此,『Thomas』 在 『nolan』 之前,因為大寫字元有較低的字碼點。 FirstName 具有不區分大小寫的排序規則。 因此,排序是按字母順序,而不是按字符的碼點。
-- insert a number of values
INSERT Employees VALUES (1,'thomas', 'john')
INSERT Employees VALUES (2,'Thomas', 'rupert')
INSERT Employees VALUES (3,'Thomas', 'Jack')
INSERT Employees VALUES (4,'Thomas', 'annie')
INSERT Employees VALUES (5,'nolan', 'John')
GO
-- ===========
SELECT EmployeeID, LastName, FirstName FROM Employees
ORDER BY LastName, FirstName
GO
-- ===========
-- specify collation: sorting uses case-insensitive collation, thus 'nolan' comes before 'Thomas'
SELECT * FROM Employees
ORDER BY LastName COLLATE Latin1_General_100_CI_AS, FirstName
GO
-- ===========
-- retrieve employee by Name
-- must use BIN2 collation for comparison in natively compiled stored procedures
CREATE PROCEDURE usp_EmployeeByName @LastName nvarchar(20), @FirstName nvarchar(10)
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS BEGIN ATOMIC WITH
( TRANSACTION ISOLATION LEVEL = SNAPSHOT,
LANGUAGE = N'us_english'
)
SELECT EmployeeID, LastName, FirstName FROM dbo.Employees
WHERE
LastName = @LastName AND
FirstName COLLATE Latin1_General_100_BIN2 = @FirstName
END
GO
-- this does not return any rows, as EmployeeID 1 has first name 'john', which is not equal to 'John' in a binary collation
EXEC usp_EmployeeByName 'thomas', 'John'
-- this retrieves EmployeeID 1
EXEC usp_EmployeeByName 'thomas', 'john'