{"id":120,"date":"2006-08-02T20:55:05","date_gmt":"2006-08-02T18:55:05","guid":{"rendered":"http:\/\/www.glorf.it\/blog\/2006\/08\/02\/sql-talk\/globale-sitzungsvariable-am-sql-server"},"modified":"2006-08-02T20:55:05","modified_gmt":"2006-08-02T18:55:05","slug":"globale-sitzungsvariable-am-sql-server","status":"publish","type":"post","link":"http:\/\/www.glorf.it\/blog\/2006\/08\/02\/sql-talk\/globale-sitzungsvariable-am-sql-server","title":{"rendered":"Globale Sitzungsvariable am SQL Server"},"content":{"rendered":"<p>Am Sybase SQL Anywhere, der zwischendrin mal auf den sch&#246;nen Namen &quot;Sybase Adaptive Server Anywhere&quot; h&#246;rte, gibt es ein Feature, was ich am &quot;Microsoft SQL Server&quot; besonders vermisse: globale Variable, die w&#228;hrend einer gesamten Session erreichbar sind.<br \/>\nSie haben einen &#228;hnlichen G&#252;ltigkeitsbereich, wie &quot;normale&quot; tempor&#228;re Tabellen beim SQL Server. Man deklariert sie einmal, kann der Wert dann beliebig setzen und in allen Batches in dieser Session darauf zugreifen.<\/p>\n<p>Eigenartigerweise bietet der SQl Srever ein Featrue an, das etwas in diese Richtig geht:<br \/>\nmit CONTEXT_INFO kann man genau einen 128 Bytes langen Wert speichern.<\/p>\n<p><b>Beispiel<\/b><\/p>\n<p>Angenommen eine Anwendung muss in Ausnahmenf&#228;llen mal eine Verbindung zu einer Datenbank aufbauen, um eine Tabelle zu erweitern oder ein Backup durchzuf&#252;hren. Normale Benutzer haben dazu nicht die entsprechenden Rechte. Die Anwendung meldet sich mit dem Datenbank-Besitzer &quot;MyDBO&quot; an, um bspw. ein neues benutzerdefiniertes Feld anzulegen. Selbstverst&#228;ndlich werden alle &#228;ndernden Operationen in einer Tabelle protokolliert, dazu kann der Benutzername mittels &quot;user_name()&quot; ermittelt werden, z.B. &quot;Thomas&quot;.<br \/>\nDie Dinge aus der Admin-Verbindung sollen auch protokolliert werden. Hier soll jetzt aber nicht der Name &quot;MyDBO&quot; notiert werden, sondern der Verursacher: &quot;Thomas&quot;.<\/p>\n<p>Zu diesem Zweck kann man gleich nach dem Aufbauen der Vrebindung den Namen des Benutzers in die CONTEXT_INFO schreiben, falls es sich um so eine Sonderverbindung handelt:<\/p>\n<p><code lang=\"sql\">declare @context_info varbinary(128);<br \/>\nset @context_info = cast(&#x0027;thomas&#x0027; as varbinary(128))<br \/>\nset context_info @context_info<\/code><\/p>\n<p>Um den Wert abzufragen, muss man beim SQL Server 2000 tief in die Trickkiste greifen und eine Systemtabelle abfragen:<\/p>\n<p><code lang=\"sql\">select cast(context_info as varchar(128))<br \/>\n\tfrom sysprocesses<br \/>\n\twhere spid=@@spid<\/code><\/p>\n<p>Wenn man nun wissen will, wer die zu protokollierende Aktion veranlasst hat, kannman das so erfragen:<\/p>\n<p><code lang=\"sql\">declare @user_info varchar(128);<br \/>\nset @user_info = (select cast(context_info as varchar(128)) from sysprocesses where spid=@@spid)<br \/>\nselect case<br \/>\n\twhen @user_info = &#x0027;&#x0027;<br \/>\n\t\tthen user_name()<br \/>\n\telse @user_info<br \/>\n\tend  as &quot;User_name&quot;<\/code><\/p>\n<p>Am SQL Server 2005 hat sich daran nicht viel ver&#228;ndert. Immerhin muss man jetzt nicht mehr die Systemtabelle abfragen:<\/p>\n<p><code lang=\"sql\">SELECT cast(CONTEXT_INFO() as varchar(128))<\/code><\/p>\n<p>Im konkreten Beispiel w&#252;rde sich das vereinfachend auswirken:<\/p>\n<p><code lang=\"sql\">select case<br \/>\n\twhen cast(CONTEXT_INFO() as varchar(128)) = &#x0027;&#x0027;<br \/>\n\t\tthen user_name()<br \/>\n\telse cast(CONTEXT_INFO() as varchar(128))<br \/>\n\tend as &quot;User_name&quot;<\/code><\/p>\n<p>Das ist f&#252;r den Obige Fall schon eine akzeptable L&#246;sung. Leider gibt es damit nur eine einzige &quot;globale&quot; Variable. Wenn man mehr ben&#246;tigt, dann muss man sich das in tempor&#228;ren Tabellen speichern. Schade, der Overhead w&#228;re zu vermeiden&#8230; <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Am Sybase SQL Anywhere, der zwischendrin mal auf den sch&#246;nen Namen &quot;Sybase Adaptive Server Anywhere&quot; h&#246;rte, gibt es ein Feature, was ich am &quot;Microsoft SQL Server&quot; besonders vermisse: globale Variable, die w&#228;hrend einer gesamten Session erreichbar sind. Sie haben einen &#228;hnlichen G&#252;ltigkeitsbereich, wie &quot;normale&quot; tempor&#228;re Tabellen beim SQL Server. Man deklariert sie einmal, kann der [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[],"_links":{"self":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/120"}],"collection":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/comments?post=120"}],"version-history":[{"count":0,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/120\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/media?parent=120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/categories?post=120"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/tags?post=120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}