2010-03-16 3 views
6

Freunde,Implementieren einer C/C++ - Stil Union als eine Spalte in MySQL

Ich habe eine seltsame Notwendigkeit und kann mich nicht durch das Problem denken. Das große und mächtige Google ist aufgrund des Keyword-Recyclings (wie Sie sehen werden) wenig hilfreich. Kannst du helfen?

Was ich tun möchte, ist das Speichern von Daten mehrerer Arten in einer einzigen Spalte in MySQL.

Dies ist die Datenbank, die einer C-Union entspricht (und wenn Sie nach MySQL und Union suchen, erhalten Sie offensichtlich eine ganze Menge Sachen über das UNION-Schlüsselwort in SQL).

[Konstruierter und vereinfachter Fall folgt] Also, lassen Sie uns sagen, dass wir Leute haben - die Namen haben - und STORMTROOPERS - die TK-Nummern haben. Sie können nicht sowohl einen Namen als auch eine TK-Nummer haben. Du bist entweder BOB SMITH -oder- TK409.

In CI könnte dies als eine Union auszudrücken, etwa so:

union { 
     char * name; 
     int tkNo; 
     } EmperialPersonnelRecord; 

Dies macht es so, dass ich entweder bin einen Zeiger auf einen char-Array oder eine ID in der Art EmperialPersonnelRecord speichern, aber nicht beide.

Ich bin auf der Suche nach einem MySQL-Äquivalent auf einer Spalte. Meine Spalte würde entweder ein int, double oder varchar (255) (oder eine andere Kombination) speichern. Würde aber nur den Platz des größten Elements einnehmen.

Ist das möglich?

(natürlich alles möglich ist genügend Zeit, Geld und will - ich meine, ist es möglich, wenn ich bin arm, faul und auf einer Frist ... Auch bekannt als „out of the box“)

+0

ich mit einer Art und Weise beantwortet, es zu tun, etwas gegossen und hängen aber können Sie bitte erarbeiten Warum willst/musst du? Es scheint, dass die naheliegende Lösung, alle separaten Attribute in separaten NULL-fähigen Spalten zu speichern, gut funktioniert. – DVK

Antwort

3

Wie a1ex07 sagte, können Sie es tun, indem Sie String-Darstellung speichern. Wenn Sie jedoch Bedenken hinsichtlich des Speicherplatzes haben, wird das Speichern realer Werte in mehreren NULL-fähigen Spalten wahrscheinlich mehr Speicherplatz sparen.

Alternativ können Sie Hilfstabellen erstellen und normalisieren, z.

Ihr Mangel:

 
TABLE1 
|id|name_or_TK#| 

Ihre tun können:

 
TABLE1 
|id|name|TK| 

oder Sie können dieses Problem der Handhabung

 
TABLE1 
|id|ST_or_human_flag|other columns common to humans and stormtroopers 

TABLE2 - Names_of_humans 
|id|name| 

TABLE3 - TKs_of_STs 
|id|TK| 
+0

DVK - Platz und Leistung sind meine Hauptanliegen. Ich wusste nicht, dass Sie Platz mit null-fähigen Spalten sparen - ich dachte, dass der Platz für sie reserviert wurde und der Wert einfach nicht da war. Ausgezeichnete Optionen - danke. – Michael

+0

Sie sparen nicht Platz für Spalten fester Länge (z. B. Ints), aber wird definitiv auf Varchar Einsen speichern. Siehe http://stackoverflow.com/questions/556363/space-used-by-nulls-in-database für eine gute Einführung – DVK

+0

Was die Leistung betrifft, hängt der Unterschied zwischen 2D- und 3D-Lösung vollständig davon ab, welche Abfragen auf dem Server ausgeführt werden Tabelle (n), aber beide werden definitiv das "alles in einer Zeichenkodierung speichern" wegen der Notwendigkeit, zu anderen Datentypen zu konvertieren. – DVK

1

Nein, Es gibt keinen Spaltetyp "Union". Sie können jedoch eine Spalte erstellen, die groß genug ist, um das größte Element aufzunehmen, und eine andere Spalte, die als Typkennzeichen fungiert. I.e.

+0

a1ex07 ~ Das ist eine großartige Antwort und es war der Punkt, an dem ich mich lehnte. Ich hatte gehofft, Funktionen (min, max, sum) auf den Int-Typen, String-Matching auf den String-Typen, usw. tun zu können. Das würde nicht ganz funktionieren. Also, in meiner Traumwelt, könnte ich dies tun: wählen Sie * aus der Tabelle, wo WEIRD_COL.int zwischen 1 und 10; Wählen Sie * aus der Tabelle wo WEIRD_COL.string wie "S * O *"; usw. (nicht sicher, was der * würde mich in der Spaltenliste bekommen). – Michael

+0

@ user81338 - Aggregation usw. (was ein großer Punkt ist), müssen Sie in> 1 Tabelle zu normalisieren. Siehe meine Antwort unter – DVK

1

C Gewerkschaften sind ein ziemlich Bit-twiddly Art und Weise tun.

Was Sie dort haben, ist ein polymorpher Datentyp. Eine Möglichkeit, das Problem zu lösen, besteht also darin, zu einer objektorientierten DB zu wechseln, die dynamisch typisiert wird, wie einige der "NoSQL" -Daten.

Wenn Sie mit der aktuellen relationalen DB bleiben müssen, können Sie die Standard-Sache, die eine Art von ORM - objekt-relationalem Mapper - für die Übersetzung erstellen.Eine Möglichkeit besteht darin, die allgemeinen Felder ("Basisklassen") in die Haupttabelle zusammen mit einer Typspalte einzufügen und dann mit der Spalte type auszuwählen, welche Tabelle der "Blattklasse" die zusätzlichen Felder enthält. Zum Beispiel:

table Employee 
    field id int 
    field emp_type enum('human', 'stormtrooper') 
    field salary int 
    field division_id int 
    field manager_id int 

table HumanEmployee 
    field emp_id int 
    field name string 

table StormtrooperEmployee 
    field emp_id int 
    field tk_number int 

Das heißt, zurück zur Basis Tabelle Mitarbeiter durch Mitarbeiter-ID die * Arbeitnehmer Tabellen gebunden.

+1

Ich kicherte über die Idee eines Sturmsoldaten mit einem Manager der mittleren Ebene :) Ich stimme darin überein, dass Gewerkschaften seltsam sind, aber ich versuche, das Problem auf den atomarsten (kleinsten unteilbaren, nicht radioaktiven) Fall zu reduzieren, und das beschreibt es. – Michael

0

Ich glaube, Sie zwei unterschiedliche Spalten und Speichern von Daten entsprechend haben sollte, wenn das Abrufen Sie können sie zusammen wie col1 + col2 als full_name