En dehors des aspects techniques et des solutions de rechange proposées (en utilisant des VARCHAR(27)
colonnes) discutés dans la réponse de @ Joe , je remets en question la " nécessité de créer [un] tableau dénormalisé large" tel qu'exprimé par le PO Sauf s'il existe une exigence technique étrange que toutes ces colonnes doit être dans une seule table, je suggère / recommande de les répartir sur autant de tables "frères" que nécessaire. Les tables fratries étant des tables qui:
- avoir une relation 1 à 1 les uns avec les autres,
- tous ont exactement la même clé primaire,
- un seul a la
IDENTITY
colonne (et pas de FK pour les autres)
- les autres ont une clé étrangère (sur la colonne PK) pointant vers le PK de la table qui a le
IDENTITY
Ici, vous divisez la ligne logique sur deux ou plusieurs tables physiques. Mais c'est essentiellement ce qu'est la normalisation de toute façon, et ce que les bases de données relationnelles sont conçues pour gérer.
Dans ce scénario, vous encourez un espace supplémentaire utilisé en dupliquant le PK, et une complexité de requête supplémentaire en raison de la nécessité soit INNER JOIN
des tables ensemble (fréquemment mais pas toujours, sauf si toutes les SELECT
requêtes utilisent toutes les colonnes, mais cela ne se produit généralement pas) ou créez une transaction explicite vers INSERT
ou UPDATE
entre eux ( DELETE
peut être gérée via ON DELETE CASCADE
set sur le FK).
CEPENDANT, vous bénéficiez des avantages d'un modèle de données approprié avec des types de données natifs appropriés, et pas de supercherie qui pourrait avoir des conséquences imprévues plus tard. Même si l'utilisation VARCHAR(27)
permet à cela de fonctionner au niveau technique, je ne pense pas que le stockage de décimales sous forme de chaînes soit dans votre / le meilleur intérêt du projet.
Donc, si vous "n'avez besoin" que d'une seule table car vous ne réalisez pas qu'une seule entité logique n'a pas besoin d'être représentée physiquement dans un seul conteneur, n'essayez pas de forcer tout cela dans une seule table quand cela fonctionnera. gracieusement sur plusieurs tables.
L'exemple ci-dessous illustre le concept de base:
INSTALLER
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
TESTER
EXEC #TestInsert 'aa', 454567678989;
EXEC #TestInsert 'bb', 12312312312234;
SELECT *
FROM tempdb.dbo.T1
INNER JOIN tempdb.dbo.T2
ON T2.[ID] = T1.[ID];
Retour:
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
champs dans une table, sans compression de page ou compression décimale. En activant la compression vardécimale mais pas la page, la surcharge passe à plus de 1 K. Il y a une chance extérieure que vous puissiez stocker plus de champs par page sans vardécimal, selon vos valeurs.