2011-04-20 8 views
3

Je suis en train de concevoir une base de données en utilisant MSSQL server 2005 pour stocker les valeurs de journaux de différents périphériques. Le type de données des valeurs peut être booléen, int-32 ou 64 bits doubleQuelle est la meilleure façon de stocker plusieurs types de données dans la base de données

Il y aura une table de recherche appelé channels:

ID(PK)  | int32 

device_name | varchar(32) 

Il y aura une table appelée values pour stocker la valeur. Donc, boolean et int-32, les valeurs doubles seront castés au type de données DECIMAL.

ID(foreign key to [email protected]) | int32 

logtime       | DATETIME 
value       | DECIMAL 

La raison pour laquelle je fais ce qui est l'utilisateur final peut sélectionner les données à l'aide d'une simple déclaration de sélection sur une table, comme select logtime,value from values where ID = 1 sans connaître le type de données du canal.

Mais c'est un gaspillage de mémoire, puisque maintenant j'ai stocké int32 et booléen à Decimal. Je suis nouveau à la programmation de base de données, je me demande si quelqu'un sait une meilleure façon de le faire?

+0

espace disque est pas cher - Je pense que votre approche initiale (convertir en décimal) est optimale, pas besoin de bidouiller avec des valeurs nulles ou des champs différents. – Arvo

Répondre

3

Vous pouvez stocker 3 champs individuels qui sont nullables. Deux auront la valeur NULL, le troisième aura la valeur réelle (vous pouvez même appliquer avec une contrainte CHECK que l'un des trois n'est pas NULL). Les valeurs NULL n'occupent aucun espace. Vous pouvez ajouter une valeur calculée qui expose la valeur non nulle en tant que pseudo-colonne.

Vous pouvez également utiliser un champ sql_variant. sql_variant peut stocker plusieurs types et conserver les métadonnées de type (type, précision, échelle).

+0

Je pense que la première solution est meilleure, je ne suis pas sûr du type de surcharge que sql_variant va m'apporter. – LOK

0

En utilisant 3 champs individuels qui sont nullables, j'ai créé une vue appelée mixedNumericView que utilise CASE pour sélectionner la colonne de droite. Je suppose que l'utilisation de CASE est peu coûteuse, ai-je raison? Des moyens alternatifs de le faire? La fréquence de journal peut être jusqu'à chaque minute, je veux m'assurer que c'est la meilleure manière de choisir des données.

SELECT [ID], [logtime] 
     ,'value' = 
     CASE 
     WHEN [intValue] is not NULL THEN [intValue] 
     WHEN [bitValue] is not NULL THEN [bitValue] 
     WHEN [floatValue] is not NULL THEN [floatValue] 
     ELSE NULL 
     END 
    FROM [dbo].[mixedNumericView] 
+0

Vous pouvez utiliser une colonne calculée sur la table elle-même: 'ALTER TABLE ... ADD [valeur] AS COALESCE (IntValeur, COALESCE (bitValue, floatValue))' –

+1

@Remus - Ou 'COALESCE (IntValue, bitValue, floatValue)' probablement. –

+1

@Martin: Je suppose que c'était le bon moment pour moi d'apprendre que coalesce accepte une liste ouverte d'arguments ... –

1

Voici un exemple d'une contrainte CHECK qui assure exactement l'un des trois IS NOT NULL

ALTER TABLE MyTable WITH CHECK 
ADD CONSTRAINT CK_MyTable_ColumNulls CHECK(
(CASE 
    WHEN col1 IS NOT NULL 
     THEN 1 
    WHEN col2 IS NOT NULL 
     THEN 2 
    WHEN col3 IS NOT NULL 
     THEN 3 
    ELSE 
     500 
END) 
= 
(CASE 
    WHEN col3 IS NOT NULL 
     THEN 3 
    WHEN col2 IS NOT NULL 
     THEN 2 
    WHEN col1 IS NOT NULL 
     THEN 1 
    ELSE 
     600 
END) 
) 
Questions connexes