Ngoài các khía cạnh kỹ thuật và đề xuất xung quanh (sử dụng VARCHAR(27)
các cột) được thảo luận trong câu trả lời của @ Joe , tôi đặt câu hỏi về " cần tạo [một] bảng không chuẩn hóa rộng" như được thể hiện bởi OP Trừ khi có một số yêu cầu kỹ thuật kỳ lạ rằng tất cả các cột này phải ở trong một bảng duy nhất, tôi muốn đề xuất / khuyên bạn nên trải rộng chúng ra càng nhiều bảng "anh chị em" nếu cần. Các bảng anh chị em là các bảng:
- có mối quan hệ 1-1 với nhau,
- tất cả đều có cùng khóa chính,
- chỉ một người có
IDENTITY
cột (và không có FK cho người khác)
- phần còn lại có Khóa ngoài (trên cột PK) chỉ vào PK của bảng có
IDENTITY
Ở đây bạn đang chia anh ta hàng logic trên hai hoặc nhiều bảng vật lý. Nhưng đó thực chất là những gì bình thường hóa và dù sao thì cơ sở dữ liệu quan hệ được thiết kế để xử lý.
Trong kịch bản này, bạn phải chịu một số không gian bổ sung được sử dụng bằng cách sao chép PK và một số phức tạp truy vấn bổ sung do cần phải kết hợp INNER JOIN
các bảng với nhau (thường xuyên nhưng không phải luôn luôn, trừ khi tất cả các SELECT
truy vấn sử dụng tất cả các cột, nhưng điều đó thường không xảy ra) hoặc tạo một Giao dịch rõ ràng để INSERT
hoặc UPDATE
chúng cùng nhau ( DELETE
có thể được xử lý thông qua ON DELETE CASCADE
thiết lập trên FK).
TUY NHIÊN, bạn nhận được những lợi ích của việc có một mô hình dữ liệu phù hợp với các kiểu dữ liệu gốc, phù hợp và không có mánh khóe nào có thể gây ra hậu quả không lường trước sau này. Ngay cả khi việc sử dụng VARCHAR(27)
cho phép điều này hoạt động ở cấp độ kỹ thuật, thực tế tôi không nghĩ việc lưu trữ số thập phân vì các chuỗi là lợi ích tốt nhất của bạn / dự án.
Vì vậy, nếu bạn chỉ "cần" một bảng duy nhất do không nhận ra rằng một thực thể logic đơn lẻ không cần phải được biểu diễn vật lý trong một thùng chứa duy nhất, thì đừng cố ép tất cả những thứ này vào một bảng khi nó sẽ hoạt động duyên dáng trên nhiều bảng.
Ví dụ dưới đây minh họa khái niệm cơ bản:
THIẾT LẬP
CREATE TABLE tempdb.dbo.T1
(
[ID] INT NOT NULL IDENTITY(11, 2) PRIMARY KEY,
[Col1] VARCHAR(25),
[Col2] DATETIME NOT NULL DEFAULT (GETDATE())
);
CREATE TABLE tempdb.dbo.T2
(
[ID] INT NOT NULL PRIMARY KEY
FOREIGN KEY REFERENCES tempdb.dbo.T1([ID]) ON DELETE CASCADE,
[Col3] UNIQUEIDENTIFIER,
[Col4] BIGINT
);
GO
CREATE PROCEDURE #TestInsert
(
@Val1 VARCHAR(25),
@Val4 BIGINT
)
AS
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRAN;
DECLARE @InsertedID INT;
INSERT INTO tempdb.dbo.T1 ([Col1])
VALUES (@Val1);
SET @InsertedID = SCOPE_IDENTITY();
INSERT INTO tempdb.dbo.T2 ([ID], [Col3], [Col4])
VALUES (@InsertedID, NEWID(), @Val4);
COMMIT TRAN;
END TRY
BEGIN CATCH
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK TRAN;
END;
THROW;
END CATCH;
SELECT @InsertedID AS [ID];
GO
KIỂM TRA
EXEC #TestInsert 'aa', 454567678989;
EXEC #TestInsert 'bb', 12312312312234;
SELECT *
FROM tempdb.dbo.T1
INNER JOIN tempdb.dbo.T2
ON T2.[ID] = T1.[ID];
Trả về:
ID Col1 Col2 ID Col3 Col4
11 aa 2017-07-04 10:39:32.660 11 44465676-E8A1-4F38-B5B8-F50C63A947A4 454567678989
13 bb 2017-07-04 10:41:38.180 13 BFE43379-559F-4DAD-880B-B09D7ECA4914 12312312312234
DECIMAL(26, 8) NULL
trường vào một bảng mà không cần nén trang hoặc nén thập phân. Kích hoạt tính năng vardecimal nhưng không nén trang, chi phí nhảy vọt lên trên 1 K. Có khả năng bên ngoài là bạn sẽ có thể lưu trữ nhiều trường hơn trên mỗi trang mà không cần vardecimal, tùy thuộc vào giá trị của bạn.