这是可能的存储串与使用同一列不同的排序规则SQL_VARIANT:
CREATE TABLE dbo.Localized
(
text_id INTEGER NOT NULL,
lang_id INTEGER NOT NULL,
text_body SQL_VARIANT NOT NULL,
CONSTRAINT [PK dbo.Localized text_id, lang_id]
PRIMARY KEY CLUSTERED (text_id, lang_id),
)
GO
INSERT dbo.Localized
(text_id, lang_id, text_body)
VALUES
(1001, 2057, N'Database problems' COLLATE Latin1_General_CI_AS);
GO
INSERT dbo.Localized
(text_id, lang_id, text_body)
VALUES
(1001, 1025, N'قاعدة بيانات المشاكل' COLLATE Arabic_CI_AS)
此设计具有多个缺点(包括限制为8000个字节),尤其是在搜索区域中:SQL_VARIANT
不能被全文索引,并且某些字符串比较功能(例如LIKE
)也不能直接使用。在另一方面,它是可以创建定期索引SQL_VARIANT
并执行更为基本的比较(例如,<=,>)在核对感知方式:
CREATE UNIQUE INDEX uq1 ON dbo.Localized (text_body)
GO
-- One row
SELECT
l.*
FROM dbo.Localized AS l
WHERE
l.text_body = CONVERT(SQL_VARIANT, N'Database problems' COLLATE Latin1_General_CI_AS)
-- No rows (and no collation error!)
SELECT
l.*
FROM dbo.Localized AS l
WHERE
l.text_body = CONVERT(SQL_VARIANT, N'Database problems' COLLATE Arabic_CI_AS)
-- One row, index seek, manual version of "LIKE 'D%'"
SELECT
l.*
FROM dbo.Localized AS l
WHERE
l.text_body >= CONVERT(SQL_VARIANT, N'D' COLLATE Latin1_General_CI_AS)
AND l.text_body < CONVERT(SQL_VARIANT, N'E' COLLATE Latin1_General_CI_AS)
我们还可以编写通常的程序:
CREATE PROCEDURE dbo.GetLocalizedString
@text_id INTEGER,
@lang_id INTEGER,
@text_body SQL_VARIANT OUTPUT
AS
BEGIN
SELECT
@text_body = l.text_body
FROM dbo.Localized AS l
WHERE
l.text_id = @text_id
AND l.lang_id = @lang_id
END
GO
DECLARE @text SQL_VARIANT
EXECUTE dbo.GetLocalizedString
@text_id = 1001,
@lang_id = 1025,
@text_body = @text OUTPUT
SELECT @text
当然,在“所有翻译的单一表”设计中,全文索引也是有问题的,因为全文索引(所有索引)要求每列设置语言ID 。Joop Eggen描述的多表设计可以全文索引(尽管自然每个表需要一个索引)。
另一个主要选项是在基表中每个语言环境具有一列:
CREATE TABLE dbo.Example
(
text_id INTEGER NOT NULL,
text_2057 NVARCHAR(MAX) COLLATE Latin1_General_CI_AS NULL,
text_1025 NVARCHAR(MAX) COLLATE Arabic_CI_AS NULL,
CONSTRAINT [PK dbo.Example text_id]
PRIMARY KEY CLUSTERED (text_id)
)
这种安排确实具有一定的简单性,并且可以与全文索引一起使用,尽管它确实需要在每种新语言中添加新的列,而且许多开发人员发现这种结构使用起来很拙劣和不令人满意。
每个替代方案都有优点和缺点,并且需要在某种程度上进行间接调用,因此它可能取决于相关开发人员在最容易找到这种间接调用的位置。我想大多数人会出于大多数目的而选择多表设计。