Forums Neueste Beiträge
 

Benutzerdefinierte Datentypen

07/02/2009 - 23:11 von Heiko Heinrich-Nestler | Report spam
Hallo zusammen,

wir möchten in unserem Datenbankprojekt bei VARCHAR-Feldern
benutzerdefinierte Datentypen einsetzen, stoßen dabei aber auf einige
Probleme.

1) Für den Zugriff auf die Daten setzen wir ausschließlich StorProc's
ein, die sehr oft mit temp. Tabellen arbeiten. Wenn wir aber temp.
Tabellen mit den benutzerdefinierte Datentypen anlegen, gibt es ein
Fehler, weil die tempdb diese Typen nicht kennt. Wenn wir unsere
benutzerdefinierte Datentypen auch in der tempdb anlegen, dann
funktioniert das Anlegen der temp. Tabellen mit benutzerdefinierte
Datentypen problemlos. Allerdings tut sich hier das nàchste Problem
auf. Nach einem Neustart des SQLServers sind die benutzerdefinierte
Datentypen aus der tempdb verschwunden. Nun haben wir gelesen, dass
man die benutzerdefinierte Datentypen auch in der model-Datenbank
anlegen kann, da die tempdb beim Neustart aus der model aufgebaut
wird. Ist diese Vorgehen richtig oder gibt es eine bessere Lösung?

2) In unseren StorProc's verwenden wir oft das Konstrukt SELECT *,
meineNeueSpalte = CAST(NULL AS MyDataType) INTO #meineTempTabelle
FROM meineTabelle. Der SQLServer erlaubt aber beim CAST bzw. beim
CONVERT keine Verwendung von benutzerdefinierte Datentypen. Gibt es
hierfür eine Lösung?


Bei den beschrieben Problemen ist die Verwendung von
benutzerdefinierte Datentypen ja fast unmöglich bzw. stark
eingeschrànkt. Wie seht Ihr das?

Wir setzen übrigens den SQLServer 2005 ein und wollen demnàchst auf
SQLServer 2008 umsteigen.


Schöne Grüße aus Bayern

Heiko Heinrich-Nestler
 

Lesen sie die antworten

#1 Elmar Boye
08/02/2009 - 11:35 | Warnen spam
Hallo Heiko,

Heiko Heinrich-Nestler schrieb:
wir möchten in unserem Datenbankprojekt bei VARCHAR-Feldern
benutzerdefinierte Datentypen einsetzen, stoßen dabei aber auf einige
Probleme.

1) Für den Zugriff auf die Daten setzen wir ausschließlich StorProc's
ein, die sehr oft mit temp. Tabellen arbeiten. Wenn wir aber temp.
Tabellen mit den benutzerdefinierte Datentypen anlegen, gibt es ein
Fehler, weil die tempdb diese Typen nicht kennt.



Das Problem sollte nicht auftreten, wenn der Typ bereits zum
Zeitpunkt der Kompilierung bekannt ist.
Wird eine Spalte eines Types in eine andere Datenbank übertragen,
so wird der Basisdatentyp verwendet.
Typen sind Datenbank (Domànen) spezifisch - eine Namensgleichheit
in einer anderen bewirkt dabei nichts, dort ist es ein eigener Typ.

Verwendet werden sollte ab SQL Server 2005 nur CREATE TYPE:
<URL:http://msdn.microsoft.com/de-de/lib...7.aspx>

Nun haben wir gelesen, dass
man die benutzerdefinierte Datentypen auch in der model-Datenbank
anlegen kann, da die tempdb beim Neustart aus der model aufgebaut
wird.



Das gilt zwar, sowohl für sp_addtype als auch für CREATE TYPE:
<URL:http://msdn.microsoft.com/de-de/lib...3.aspx>

Nur ist das Ändern der Model Datenbank immer etwas problematisch.
Insbesondere wenn eure Software auf Servern laufen soll,
die nicht von euch installiert und stàndig betreut werden
oder auf denen Datenbanken anderer Hersteller installiert werden.
Und eine eigene Instanz wird nicht nicht immer akzeptiert.

Bei CREATE TYPE wàre das nicht erforderlich, da in der tempdb
der Basisdatentyp (z. B. VARCHAR(n)) verwendet wird.

2) In unseren StorProc's verwenden wir oft das Konstrukt SELECT *,
meineNeueSpalte = CAST(NULL AS MyDataType) INTO #meineTempTabelle
FROM meineTabelle. Der SQLServer erlaubt aber beim CAST bzw. beim
CONVERT keine Verwendung von benutzerdefinierte Datentypen. Gibt es
hierfür eine Lösung?



Leider nein. CAST/CONVERT erlauben nur die Basisdatentypen.

Oben wird es zwar via ALTER TABLE funktionieren. Nur da benutzerdefinierte
Typen auf Datenbankebene definiert werden, muß er in der tempdb existieren.
Aber selbst wenn der Typ in tempdb angelegt wird, ist es ein eigener -
auch wenn er (zufàllig) die gleiche Spezifikation hat.
Eine zusàtzliche Sicherheit bietet es also nicht.

Bei den beschrieben Problemen ist die Verwendung von
benutzerdefinierte Datentypen ja fast unmöglich bzw. stark
eingeschrànkt. Wie seht Ihr das?



Ich persönlich habe mich von benutzerdefinierten Typen
bereits bei SQL Server 7 verabschiedet, wo ich anfangs
damit geliebàugelt hatte.

Denn auf Seite des Client ist nur der Basisdatentyp bekannt.
Und liefert er z. B. eine Zeichenkette zu großer Lànge,
so kommt es zum Fehler. Und weicht gar der Basistyp
ab (z. B. int anstatt varchar), so gibt es noch mehr Probleme.
Einschrànkungen (CHECK, DEFAULT) wiederum müssen auf
Tabellenebene definiert werden, so dass die Integritàt
dort definiert wird.

Summa Summarum: Für den Entity oder Domànen-Entwurf würde
ich mit "Typen" arbeiten, beim Übertragen in das SQL Server
Modell darauf verzichten.

Wir setzen übrigens den SQLServer 2005 ein und wollen demnàchst auf
SQLServer 2008 umsteigen.



SQL Server 2008 bietet zuàtzlich Tabellentypen - siehe obiger Link.
Änderungen an Spaltentypen gibt es nicht.

Ich habe unten mal ein Skript zum Experimentieren angehàngt,
der sp_addtype und die Anlage in tempdb ist auskommentiert.

Gruß Elmar

USE Northwind
GO


IF NOT EXISTS(SELECT * FROM sys.types WHERE name = N'ssn_type')
CREATE TYPE dbo.ssn_type
FROM varchar(11) NOT NULL;
GO

CREATE TABLE dbo.Person
(
Id int not null PRIMARY KEY,

Ssn ssn_type
CONSTRAINT CK_Person_Ssn CHECK ( Ssn LIKE '[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]' )
);
GO

INSERT INTO dbo.Person VALUES(1, '078-05-1120');

INSERT INTO dbo.Person VALUES(2, '078-05-1120-9999');

INSERT INTO dbo.Person VALUES(3, 'abc-de-fghi')
GO

SELECT *
INTO #Person
FROM dbo.Person;
GO

/* Optional: Anlage eines Type mit gleicher Definition in tempdb

EXEC tempdb..sp_executesql N'IF NOT EXISTS(SELECT * FROM sys.types WHERE name = N''ssn_type'')
CREATE TYPE ssn_type
FROM varchar(11) NOT NULL;', N''

EXEC tempdb..sp_executesql N'ALTER TABLE #Person ADD SsnNeu ssn_type', N''

*/
GO

SELECT * FROM #Person;
GO
SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, DOMAIN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Person'
GO
EXEC tempdb..sp_help '#Person'
GO

DROP TABLE #Person;
GO
DROP TABLE dbo.Person;
GO
DROP TYPE dbo.ssn_type;
GO
GO

Ähnliche fragen