{"id":519,"date":"2016-02-21T19:57:46","date_gmt":"2016-02-21T17:57:46","guid":{"rendered":"http:\/\/www.flip-design.de\/?p=519"},"modified":"2016-02-21T19:57:46","modified_gmt":"2016-02-21T17:57:46","slug":"user-defined-types-in-sql-server","status":"publish","type":"post","link":"https:\/\/www.flip-design.de\/?p=519","title":{"rendered":"User defined types in SQL Server"},"content":{"rendered":"<p>Zuletzt hatte ich das Problem, dass ich tempor\u00e4re Daten in einer TABLE-Variable hatte und diese in einer Tabellenwert Funktion weiter verarbeiten musste. Problem dabei war, wie gebe ich meine Tabelle an die Funktion weiter?<\/p>\n<p>Die erste Idee war, dass ich eine tempor\u00e4re Tabelle erstelle und die Daten dort platziere und dann in der Funktion lese &#8211; tsja, dass geht leider nicht, bzw. dies l\u00e4sst der SQL Server nicht zu.<\/p>\n<p>Okay, und nun? Da diese Funktionalit\u00e4t st\u00e4ndig zur Verf\u00fcgung (zur Verwendung in einem SSRS Bericht) stehen musste, brauchte ich eine stabile und multiuser-f\u00e4hige L\u00f6sung.<\/p>\n<p>N\u00e4chste Idee w\u00e4re, eine physische Tabelle zu erstellen und darin die Daten zu speichern. F\u00fcr die multiuser-F\u00e4higkeit k\u00f6nnte ich Prozess- oder die Benutzer ID aufnehmen&#8230;\u00a0ist aber irgendwie umst\u00e4ndlich, da einerseits Berechtigungen auf die Tabelle erteilt werden m\u00fcssen, Indizierung, Speicher etc &#8230;<\/p>\n<p>Die L\u00f6sung war nun, benutzerdefinierte Typen im SQL Server zu erstellen. Bisher kannte ich das mehr von CLR&#8217;s, aber der SQL Server bietet bereits seit Version 2008 die M\u00f6glichkeit, eigene Typen f\u00fcr Tabellenwert-Variablen zu erstellen.<\/p>\n<p>Via CREATE TYPE wird der Typ mit der entsprechenden Definition erstellt, bspw.:<\/p>\n<pre>CREATE TYPE tmpDataType As Table (\r\n data VARCHAR(255));\r\nGO<\/pre>\n<p>Aus diesem Type kann dann ein entsprechendes Objekt erstellt werden:<\/p>\n<pre>DECLARE @tmpDataTable As tmpDataType;<\/pre>\n<p>Dieses Objekt kann dann wie eine bisherige Tabellenwert Variable mit Daten bef\u00fcllt werden. Das Verhalten ist v\u00f6llig identisch mit den bisherigen Tabellewert Variablen, die Daten k\u00f6nnen darin manipuliert, erg\u00e4nzt oder gel\u00f6scht werden. \u00a0Der eigentliche Vorteil ist nun, dass ich dieses Objekt an eine Funktion weitergeben kann:<\/p>\n<pre>CREATE FUNCTION dbo.testFunc(@tmpDataTable tmpDataType READONLY)\r\nRETURNS TABLE\r\nRETURN (\r\n -- return the data or do somethin else ...\r\n SELECT data FROM @tmpDataTable\r\n);\r\nGO<\/pre>\n<pre>DECLARE @tmpDataTable As tmpDataType;<\/pre>\n<pre>INSERT INTO @tmpDataTable\r\nSELECT data FROM dbo.data;<\/pre>\n<pre>SELECT * FROM dbo.testFunc(@tmpDataTable);\r\nGO<\/pre>\n<p>&nbsp;<\/p>\n<p>Das war&#8217;s schon!<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Vollst\u00e4ndiges Demo-Script (<strong>Verwendung auf eigene Gefahr!<\/strong>)<\/p>\n<pre>-- create a tmp.-DB\r\nCREATE DATABASE TYPETEST;\r\nGO\r\nUSE TYPETEST;\r\nGO\r\n-- create a demo table\r\nCREATE TABLE dbo.data (\r\n id INT not null primary key identity(1,1)\r\n , data VARCHAR(255));\r\nGO\r\n-- insert demo data\r\nINSERT INTO dbo.data (data) VALUES ('VAL1'), ('VAL2'), ('VAL3');\r\nGO<\/pre>\n<pre>-- create a temp table\r\nCREATE TABLE ##tmpData (data VARCHAR(255));\r\nGO\r\n-- fill the demo table\r\nINSERT INTO ##tmpData\r\nSELECT data FROM dbo.data;\r\nGO<\/pre>\n<pre>-- create a function to read the demo data from the temp table\r\n--CREATE FUNCTION dbo.testFunc()\r\n--RETURNS TABLE\r\n--RETURN (\r\n-- SELECT data FROM ##tmpData\r\n--);\r\n--GO\r\n-- Does not work, in functions you do not have the option to read from temporaly tables ...\r\n-- and now?!\r\n-- but how can i move my temporally data to my function?<\/pre>\n<pre>-- one option is to create a pyhsically table with the process id ... but do you need this for sure?!\r\n-- NO!<\/pre>\n<pre>-- create a user type table variable in the database (be carefull, this is in the database a global type!!\r\nCREATE TYPE tmpDataType As Table (\r\n data VARCHAR(255));\r\nGO<\/pre>\n<pre>-- create a function with a parameter from the user defined typ\r\nCREATE FUNCTION dbo.testFunc(@tmpDataTable tmpDataType READONLY)\r\nRETURNS TABLE\r\nRETURN (\r\n -- return the data or do somethin else ...\r\n SELECT data FROM @tmpDataTable\r\n);\r\nGO<\/pre>\n<pre>-- create a object from our new type\r\nDECLARE @tmpDataTable As tmpDataType;<\/pre>\n<pre>-- fill our object with demo data\r\nINSERT INTO @tmpDataTable\r\nSELECT data FROM dbo.data;<\/pre>\n<pre>-- execute our new function\r\nSELECT * FROM dbo.testFunc(@tmpDataTable);\r\nGO<\/pre>\n<pre>-- clean up\r\nDROP TABLE ##tmpData;\r\nGO\r\nUSE tempdb;\r\nGO\r\nDROP DATABASE TYPETEST;<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Zuletzt hatte ich das Problem, dass ich tempor\u00e4re Daten in einer TABLE-Variable hatte und diese in einer Tabellenwert Funktion weiter verarbeiten musste. Problem dabei war, wie gebe ich meine Tabelle an die Funktion weiter? Die erste Idee war, dass ich &hellip; <a href=\"https:\/\/www.flip-design.de\/?p=519\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":78,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[18,10,3],"tags":[],"_links":{"self":[{"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/posts\/519"}],"collection":[{"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=519"}],"version-history":[{"count":1,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/posts\/519\/revisions"}],"predecessor-version":[{"id":520,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/posts\/519\/revisions\/520"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/media\/78"}],"wp:attachment":[{"href":"https:\/\/www.flip-design.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=519"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=519"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=519"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}