2012-12-11 5 views
13

Al momento ho un setup tabella di database come segue (EAV - motivi di lavoro sono validi):Esistono vantaggi nell'utilizzo di sql_variant rispetto a varchar in SQL Server?

  • Id - int (PK)
  • Key - unico nel suo genere, varchar (15)
  • Value - varchar (1000)

Questo mi consente di aggiungere valori misti nel mio database come coppie chiave/valore. Per esempio:

1 | 'Some Text'  | 'Hello World' 
2 | 'Some Number' | '123456' 
etc. 

Nel mio codice C# Io uso ADO.Net utilizzando reader.GetString(2); per recuperare il valore come una stringa, quindi avere il mio codice Convertire altrove in base alle esigenze, per esempio ... Int32.ParseInt(myObj.Value);. Sto cercando di migliorare la mia tabella modificando eventualmente la colonna dei valori su un tipo di dati sql_variant, ma non so quale sarebbe il vantaggio di ciò? Fondamentalmente, c'è qualche vantaggio ad avere la colonna valore di sql_variant rispetto a varchar(1000)?


Per essere più chiaro, ho letto da qualche parte che sql_variant ottiene rinviato come nvarchar (4000) al client che effettua la chiamata (ahi)! Ma, non posso lanciarlo nel suo tipo prima di restituirlo? Ovviamente il mio codice dovrebbe essere regolato per memorizzare il valore come oggetto invece di un valore stringa. Immagino, quali sono i vantaggi/svantaggi dell'uso di sql_variant rispetto ad altri tipi nella mia situazione attuale? Oh, e vale la pena ricordare che tutto quello che ho intenzione di memorizzare sono datetimes, stringhe e tipi numerici (int, decimal, ecc.) Nella colonna value; Non ho intenzione di archiviare e blob o immagini o altro.

+1

Come [Aaron Bertrand menziona nelle sue * Cattive abitudini a calci - utilizzando il tipo di dati errato *] (http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/12/bad-habits-to -kick-using-the-wrong-data-type.aspx): * Usando SQL_VARIANT affatto * - è ** non ** una buona idea. Non usarlo Non ottieni alcun vantaggio, ma molti inconvenienti ... –

+0

Al di fuori di affermare che sql_variant è sbagliato, stai dicendo che varchar (1000) è la strada da percorrere nella mia esatta situazione? –

+0

Come pensi che l'uso di un sql_variant migliorerà la tua tabella? –

risposta

7

Se si modifica il tipo su sql_variant, sarà necessario utilizzare il metodo IDataRecord.GetValue. Conserverà il tipo fino in fondo.

Quindi, in .NET vi permetterà di avere questo tipo di codice:

// read an object of SQL underlying data type 'int' stored in an sql_variant column 
object o = myReader.GetValue(); // o.GetType() will be System.Int32 

// read an object of SQL underlying data type '(n)varchar' or '(n)char' stored in an sql_variant column 
object o = myReader.GetValue(); // o.GetType() will be System.String 

// read an object of SQL underlying data type 'datetime' stored in an sql_variant column 
object o = myReader.GetValue(); // o.GetType() will be System.DateTime 

etc... 

Naturalmente, suppone di fare lo stesso durante il salvataggio. Basta impostare SqlParameter.Value sul valore opaco, non utilizzare DbType.

EAV con vari tipi (standard) come valore è l'unico caso in cui personalmente penso che sql_variant sia interessante.

Ovviamente "I ragazzi incentrati su SQLServer" (leggi: DBA) non mi piace affatto :-) Sul lato SQL Server, sql_variant non è molto pratico da usare (come indicato nei commenti), ma se la mantieni come una "cosa" opaca e non devi usarla nel codice di procedura SQL, penso che sia ok. Quindi, è più un vantaggio sul lato di programmazione .NET/OO.

1

Il tipo sql_variant ha i suoi limiti come descritto bene da Zarathos.

Quello che trovo confuso è che si menziona varchar (1000) e quindi "ouch" sulla restituzione di un nvarchar convertito (4000).

Comincerei col dire che è una buona cosa che il mondo intero abbia finalmente smesso di usare set di caratteri locali e limitati e abbia deciso di andare all in su Unicode e UTF-8, quindi dovresti preferire nvarchar su varchar e ntext over testo.

E il ritorno è nvarchar (4000) e non nchar (4000).La differenza è che qualsiasi varchar è - di dimensioni variabili, mentre il carattere di tipo semplice è fissato in dimensioni. Restituire le tuple di char (4000) invierebbe un sacco di rifiuti vuoti, ma con varchar questo non è un problema.

OK. Ma quale sarebbe un tipo di dati appropriato per te? Consiglierei ntext. Quello che era 1000 oggi potrebbe essere 10'000 domani. Se hai "molto testo" che non stai indicizzando, forse il tuo database non dovrebbe decidere quale potrebbe essere il limite. È solo testo.

ntext si adatta bene anche con .NET, poiché le stringhe sono sempre in Unicode. La conversione da stringa a int è anche più veloce in .NET rispetto a SQL Server.

Spero che questo aiuti

9

La cosa buona di variante SQL è che è possibile memorizzare diversi tipi in una colonna e mantenere le informazioni sul tipo.

Inserire in valori MySettings ('Nome', 'MyName'); Inserire in valori di MySettings ('ShouesNumber', 45); Inserire in MySettings i valori ('MyDouble', 31.32);

Se si vuole recuperare il tipo:

select SQL_VARIANT_PROPERTY (value , 'BaseType') as DataType,* from mysettings 

e si ha:

Datatype Name   Value 
----------------------------- 
varchar Name   MyName 
int  ShoesNumber 45 
numeric MyDouble  31.32 

Purtroppo questo ha diversi svantaggi:

  1. non molto veloce
  2. non benissimo Ted da ORM framework
2

non vedo che è stato ancora citato, quindi mi dire che un approccio abbastanza comune a questo problema è una tabella come questa:

  • Id - int (PK)
  • Key - unico nel suo genere, varchar (15)
  • ValueType - Integer (0 - String, 1 - Integer, 3 - Float) (opzionale)
  • StringValue - varchar (1000)
  • intValue - Intege r
  • FloatValue - Doppia

Vantaggi:

  • dati vengono salvati nella sua forma più appropriata (memorizzare interi come stringhe spreca un sacco di bit)
  • Si può fare query di fantasia come dove a sinistra (chiave, 5) = 'SCARPE' e IntValue> 5
  • La colonna ValueType è utile solo se si utilizzano prefissi/suffissi sulle proprie chiavi (per recuperare set di chiavi) e il set potrebbe essere di tipo misto. cioèDOVE sinistra (chiave, 4) = 'Taglia' e ValueType = 1

Svantaggi:

  • Ovunque in cui si utilizza questa tabella è necessario garantire che si/ottenere/impostare la colonna corretta Valore
  • Se si decide che è necessario/desidera la colonna ValueType, è necessario assicurarsi di ottenerlo/impostarlo correttamente.
+5

Con una colonna 'ValueType' e la scelta tra il riempimento di' StringValue', 'IntValue' e' FloatValue', hai reinventato con successo un 'sql_variant' che è più lavoro da usare e ha meno funzioni. –

Problemi correlati