SQL 2005 Server error: Property IsLocked is not available for Login '[username]'

Heute musste ich feststellen das auf einem Windows 2003 Server mit einer Instance vom MS SQL Server 2005 Express DotNetNuke die Arbeit eingestellt hat. Ein Blick in das Eventlog vom Server ergab, das sich der Benutzer nicht mehr am SQL-Server anmelden konnte. Als ich die Eigenschaften des entsprechenden Datenbank-Benutzers überprüfen wollte, kam die Meldung: Property IsLocked is not available for Login '[username]'. This property may not exist for this object, or may not be retrievable due to insufficient access rights. (Microsoft.SqlServer.Smo) Ein Wechsel zwischen dem Anmeldemodus Windows-Auth und gemischter Modus betrachte keine Veränderung - diesen Tipp hatte ich in einem Forum gelesen. Was geholfen hat war das absetzen vom folgendem SQL-Befehl:ALTER LOGIN [usermae] WITH PASSWORD=N'meintollespwd',CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF, DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]GOALTER LOGIN [username] ENABLE  Damit konnte sich DotNetNuke wieder anmelden und auch die Eigenschaften vom Benutzer waren wieder einsehbar und konnten über die Managmentkonsole vom SQL-Server modifiziert werden. Die wirkliche Ursache habe ich noch nicht gefunden - zumindest läuft die Webanwendung wieder!

SQL Server 2008 Modifizieren einer Tabelle

Derzeit beschäftige ich mich ein wenig mit dem SQL-Server 2008 und wollte einen ganz simple Geschichte machen: Eine bestehende Tabelle ein wenig anpassen. Beim Speichern der Daten kam aber vom Microsoft SQL Server Management Studio immer die Meldung, dass die Tabelle nicht gespeichert werden kann - mit dem Kommentar: "Speichern von Änderungen verhindern, die die Neuerstellung der Tabelle erfordern" Die Lösung dafür ist eigentlich recht simple: Man öffnet im SQL Server Managementstudio den Menüpunkt Extras -> Optionen; geht dann in den Bereich Designer -> Tabellen- und Datenbank-Designer und deaktiviert dort unter "Tabellenoptionen" die Checkbox "Speichern von Änderungen verhindern, die die Neuerstellung der Tabelle erfordern". Anschließend kann man wie gewohnt die Tabelle modifizieren und auch speichern....

T-SQL - SELECT TOP durch einen Parameter beinflussen

Heute stellte sich mir die Aufgabe eine simple Stored Procedures zu schreiben, die x Datensätze aus einer Tabelle liest. Kein Paging sondern wirklich nur eine ganz bestimmte Anzahl - halt die TOP x Datensätze. Also habe ich folgende SP geschrieben: CREATE PROCEDURE dbo.Get_Top@topCount intAS    SELECT TOP @topCount    id, col1, col2, col3   FROM TestTable   Leider wurde mir dabei immer ein Syntaxfehler ausgeworfen - die Nutzung von dem Parameter innerhalb vom SQL-Statement scheint dem SQL-Server 2005 nicht zu schmecken. Also erst mal etwas gegooglet.... und zum guten Schluß stelle sich raus das die Lösung so einfach ist - aber darauf kommt man wohl zunächst nicht. Es reicht aus um das @topCount einfach eine Klammer zu setzen und schon kann der SQL-Server die SP verarbeiten. Die lauffähige Stored Procedures für den SQL-Server sieht dann so aus: CREATE PROCEDURE dbo.Get_Top@topCount intAS    SELECT TOP (@topCount)    id, col1, col2, col3   FROM TestTable Darauf muss man erst mal kommen ;-)

Dokumentation der Dotnetnuke Datenbank (ERD) der Version 4.4.0

Wer schon immer mal eine Datenbankmodell-Digramm der DNN-Datenbank haben wollte, kann diese nun einfach downloaden. Die Datenbankstruktur der DNN-Version 4.4.0 wurde dabei dokumentiert. Es stehen drei verschiednen Formate zur Verfügung: PDF VISO HTML Windows-Hilfe Hier gib es den Download des ERD Modells

iBATIS: Ein Data Mapper framework fuer DotNet / Java

Ohne jetzt große Erfahrungen mit dem System iBATIS gemacht zu haben, kann ich sagen, dass mir die Vorgehensweise sehr gut gefällt! So um 2000 herum habe ich mit einem Kollegen eine ähnliche Datenbankzugriffskomponente entwickelt und sehr gute Erfahrungen damit gesammelt. Gerade das Auslagern der der SQL-Befehle bzw. die Abstrahierung der SQL-Befehle kann Vorteile haben. Damals haben wir dieses Konzept unter dem Aspekt der Datenbankunabhänigkeit implementiert und eine allgemeine Beschreibung in Form von XML auf die entsprechende Datenbank zur Laufzeit angepasst. Freut mich doch immer wieder wenn ich Projekte sehe, die ähnliche Methode anwenden. Mittlerweile bin ich zwar mehr der Freund vom Provider-Pattern aber der Ansatz von iBATIS kann durchaus einen Sinn ergeben! Eine weiter Diskussion erspare ich mir an dieser Stelle :) Ach so, hier gibt es noch den Link. Nur so am Rande: MySpace.com benutzt nicht nur ASP.NET 2.0 sondern auch iBATIS .. guckst Du hier!

In eine SQL Select Statement eine zufaellige Menge an Zeilen zurueckliefern

Wenn man aus einem Pool von x Zeilen, die ein Select-Statement zurückliefert, eine zufällige Auswahl an Zeilen habe möchte geht das ganz einfach so:SELECT TOP 5 NEWID() AS randomNumber, * FROM [MyTable] ORDER BY 1 In diesem SQL-Statement wird einfach eine Guid erzeugt und das Resultset nach dieser zusätzlichen Spalte sortiert. Durch die Anweisung TOP 5 werden dann auch nur die ersten fünf Zeilen im Resultset aufgeführt. Schon ist es vollbracht! Alternativ - und wie ich auch gerade festgestellt habe der von Microsoft vorgeschlagene Weg - kann man auch folgenden Befehl nutzen SELECT TOP 5 * FROM [MyTable] ORDER BY NEWID() Vorteil: Die zusätzliche Spalte randomNumber wird nicht mit in das Resultset aufgenommen und ich persönlich finde es auch etwas eleganter :)

Try/Catch Block in SQL Server 2005

Der SQL Server 2005 unterstützt nun eine deutlich bessere Fehlerbehandlung unter T-SQL - ein Try/catch Block erlaubt ein Errorhandling. Die Handhabung ist eigentlich wie bei allen Try/catch-Blöchen die man z.B. aus C#, VB.NET oder Delphi kennt. Hier ein klassisches Beispeil - divison durch 0: BEGIN TRY   DECLARE @X INT   -- Divide by zero to generate Error   SET @X = 1/0END TRYBEGIN CATCH   SELECT ERROR_NUMBER() ERNumber,   ERROR_SEVERITY() Error_Severity,   ERROR_STATE() Error_State,   ERROR_PROCEDURE() Error_Procedure,   ERROR_LINE() Error_Line,   ERROR_MESSAGE() Error_MessageEND CATCH Als Ergebnis bekommt man: Error DetectedErr_Num Err_Sev Err_State Err_Proc Err_Line Err_Msg------- ------- --------- -------------------- --------- --------------------------------8134 16 1 NULL 4 Divide by zero error encountered. Ziemlich cool und bei complexen SQL-Statements kann ddas sehr hilfreich sein!

Erster Release Candidate von MySQL 5.0 erschienen

Ende September ist der erste RC von MySQL in der Version 5 released wurden. Die aktuelle Versionsnummer lautet 5.0.13 und bietet einige Erweiterungen, die schon lange gewünscht wurden: Stored Procedures Trigger Cursors Views usw. Mehr Informationen gibt es hier im Pressebericht .... Download von MySQL 5

SQL Server and MSDE Web Interface

Ich habe gerade ein Tool gefunden mit dem man die MSDE bzw. den SQL Server auch ohne Enterprise Manager verwalten kann. Es bietet nicht die komplette Palette aber die wichtigsten Objekte können damit verwaltet werden Tabellen / Stored Procedure / User... Dieses macht natürlich besonders bei der MSDE nützlich, da man lizenzrechtlich nicht mit dem Enterprise Manager auf die MSDE zugreifen darf! http://www.aspenterprisemanager.com/ Dieses Tool ist ein webbasiertes Managementtool und OpenSoruce.

Eine kommaseparierte Liste von Integer an eine Stored Procedure uebergeben

Man kann an eine Stored Procedure im SQL - Server keine Parameter vom Typ Array übergeben. Für den IN Operator einer SQL WHERE Klausel benötigt man aber eine Auflistung von kommaseparierten Werten.Wie das mit einem nvarchar / string Parameter funktioniert habe ich bereits in diesem Blog erklärt. Nun möchte ich aber auch noch Zeigen, wie man dieses mit dem Datentyp Integer / int hinbekommt. Eine Liste von Parameter kann man nur als String an eine SP übergeben - also: '1,2,3'. CREATE PROCEDURE [dbo].[GaliNeo_Store_ProductListByProductId]@productIds nvarchar (1000)ASSELECT * FROM GaliNeo_Store_Product P WHERE (P.[ProductID] in (SELECT ID from fn_Split_varcharToint(@productIds)) )GO Der Trick hier ist eine userdefined function zu nutzen, die aus dem nvarchar Parameter eine "Tabelle" macht, die dann ohne Probleme mit dem IN Parameter verarbeitet werden kann. Die userdefined function sieht so aus: CREATE Function fn_Split_varcharToint (@IDs nvarchar(100) ) Returns @Tbl_IDs Table (ID Int) As Begin -- Append commaSet @IDs = @IDs + ',' -- Indexes to keep the position of searchingDeclare @Pos1 IntDeclare @pos2 Int-- Start from first character Set @Pos1=1Set @Pos2=1While @Pos1<Len(@IDs)BeginSet @Pos1 = CharIndex(',',@IDs,@Pos1)Insert @Tbl_IDs Select Cast(Substring(@IDs,@Pos2,@Pos1-@Pos2) As Int)-- Go to next non comma characterSet @Pos2=@Pos1+1-- Search from the next charcaterSet @Pos1 = @Pos1+1End ReturnEnd    

Dynamischer Order By Part in einer SP

Beim Schreiben von Stores Procedure möchte man von Zeit zu Zeit div. Elemente dynamisch auswählen lassen. Ein gutes Beispiel dafür ist z.B. der Order By - Part einer Abfrage. Um per Parameter dieses zu steuern hier ein Stückchen Code: declare @order int set @order = 3SELECT *FROM GaliNeo_Store_Product P LEFT JOIN GaliNeo_Store_CatProduct CP ON CP.[ProductId] = P.[ProductId]WHERE CP.[CategoryID] = 19order by      case @order     when 'productname' then [ProductName]     when 'productnumber' then P.[ProductNumber]        else null    end,    case @order     when 'productid' then P.[ProductId]        else null    end       Diesen Code habe ich im SQl Query Analyzer geschrieben und ausgeführt. Das hier zwei case - Bereiche genutzt werden liegt an den unterschiedlichen Datentypen. ProductName ist ein nvarchar und ProductId ein int Datentyp. Entweder führt man eine Konvertierung durch, besser ist aber wenn man mit zwei Konstrukten arbeitet. Eine andere Möglichkeit wäre folgende: declare @order int set @order = 3SELECT *,    case     when @order = 1 then [ProductName]     when @order = 2 then Convert(nvarchar,P.[Productid])    when @order = 3 then Convert(nvarchar,P.[ProductTypeId])    end as OrderColFROM GaliNeo_Store_Product P LEFT JOIN GaliNeo_Store_CatProduct CP ON CP.[ProductId] = P.[ProductId]WHERE CP.[CategoryID] = 19order by OrderCol  

Mit SQL die Kalenderwoche ermittlen...

Wer schon immer mal in SQL oder einer Stored Procedure die Kalenderwoche eines Datums ermittelt wollte .. hier ist die Lösung. Das SQL Statement Select Datepart(Week, Getdate()) liefert die Kalenderwoche des aktuellen Datums. Leider ist die ermittelte Kalenderwoche nicht nach europäischer bzw. deutscher Norm. Es wird automatisch der 1. Januar in die 1. Kalenderwoche gesetzt. Dieses Stored Procedure ermittelt die Kalenderwoche nach europäischer Norm. CREATE PROCEDURE dbo.ISOweek (@DATE datetime)ASBEGINDECLARE @ISOweek intSET @ISOweek = DATEPART(wk, @DATE) + 1 -DATEPART(wk, CAST( DATEPART( yy, @DATE ) AS CHAR(4) ) + '0104' )-- Jan 1-3 may belong to the previous yearIF ( @ISOweek = 0 )BEGINDECLARE @Date2 datetimeSET @DATE2 = CAST( DATEPART( yy, @DATE ) - 1 AS CHAR(4) ) +'12' + CAST( 24 + DATEPART( DAY, @DATE ) AS CHAR(2) )-- rekursiver Aufruf :(EXEC @ISOWeek = ISOWeek @DATE2SET @ISOWeek = @ISOWeek + 1END--Dec 29-31 may belong to the next yearIF ( ( DATEPART( mm, @DATE ) = 12 ) AND( ( DATEPART( dd, @DATE ) - DATEPART( dw, @DATE) ) >= 28 ) )SET @ISOweek=1RETURN(@ISOweek)END Um das allerdings auch in einer Stored Procedure (oder direkt im SQL-Statement) zu verwenden kann man auch eine Userdefined function anlegen: CREATE FUNCTION dbo.fn_ISOweek (@DATE datetime)RETURNS intASBEGINDECLARE @ISOweek intSET @ISOweek = DATEPART(wk, @DATE) + 1 -DATEPART(wk, CAST( DATEPART( yy, @DATE ) AS CHAR(4) ) + '0104' )--Jan 1-3 may belong to the previous yearIF ( @ISOweek = 0 )BEGINDECLARE @Date2 datetimeSET @DATE2 = CAST( DATEPART( yy, @DATE ) - 1 AS CHAR(4) ) +'12' + CAST( 24 + DATEPART( DAY, @DATE ) AS CHAR(2) )-- rekursiver Aufruf:EXEC @ISOWeek = ISOWeek @DATE2SET @ISOWeek = @ISOWeek + 1END--Dec 29-31 may belong to the next yearIF ( ( DATEPART( mm, @DATE ) = 12 ) AND( ( DATEPART( dd, @DATE ) - DATEPART( dw, @DATE) ) >= 28 ) )SET @ISOweek=1RETURN(@ISOweek)END Infos zur SQL Funktion DATEPART gibt es unter:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_da-db_2mic.asp    

Ermitteln des Speicherplatz von Tabellen im MS SQL-Server

Leider bietet der Enterprise Manager von MS SQL-Server nicht die Möglichkeit den benötigtem Speicherplatz eine Datenbank anzuzigen. Der SQL-Server bietet dafür aber eine Stored Procedure exec sp_MsForEachTable 'sp_spaceused ''?''' Möchte man die Größe einer ganz bestimmten Tabelle einer Datenbank im SQL-Server ermitteln dann schaut das so aus: user mydbexec sp_spaceused 'sitelog'

Fuer jeden Satz mit x gibt es auch eine Loesung

Heute habe ich mich noch mal um die Suche in Benutzerprofilen bzw. in der Tabelle ASPNET_PROFILE gekümmert. Um wirklich eine gute Performance zu erreichen. wird man nicht eine redundanten Datenhaltung nicht vermeiden können. Um nicht den DotNetNuke - Core, Tabellen oder aber die Stored Proceduren von DNN zu verändern, habe ich mich dann für Trigger direkt im MS SQL Server entschieden. Die Erstellung des Triggers war zunächst etwas problematisch, da man innerhalb eines Trigger nicht auf ein Feld vom Typ "nText" zugreifen kann. Änder der Datentypen wollte ich ja vermeiden und so habe ich einfach die Daten aus der Orginaltabelle gelesen. Klappt perfekt und die redundante Datenhaltung tut jetzt auch schon fast gar nicht mehr weh :) Wichtig ist nur das man mit einem Trigger arbeitet, der ausgelöst wird nachdem die Aktion insert ode update durchgeführt wurde. Beispielhaft sieht das dann so aus: CREATE TRIGGER GaliNeo_ASPPROFILE_Update  ON [dbo].[aspnet_Profile] FOR INSERT, UPDATEAS DECLAR @sPostalCode varchar(5) DECLARE @sUserId char(100)DECLARE @iUserId intDECLARE @sUserName nvarchar(50) /*die aktuelle UserId ermittlen, die vom update betroffen ist */select @sUserId=Userid from inserted /*Benutzername aus der Tabelle ermittlen, damit die DNN-UserId ermittelt werden kann*/SELECT @sUserName = [UserName] FROM ASPNET_USERS WHERE [UserId] = @sUserId /*Die DNN-UserId wird ermittlet */SELECT @iUserId = [UserId] FROM Users WHERE [UserName] = @sUserName /*Ermitteln der geänderten Daten direkt aus der Orginaltabelle */SELECT @sPostalCode=dbo.fn_GetProfileElement('PostalCode',PropertyNames,PropertyValuesString)FROM ASPNET_PROFILE WHERE [USERID] = @sUserId   IF ((SELECT count(*) FROM GaliNeo_User_Profile WHERE [UserId] = @iUserId)= 0)begin INSERT INTO GaliNeo_User_Profile ( [UserId], [PostalCode], ) VALUES ( @iUserId, @sPostalCode, )endelsebegin  UPDATE GaliNeo_User_Profile SET  [PostalCode] = @sPostalCode  WHERE [UserId] = @iUserId end    

Der beruehmte Satz mit "x" ....

Mal wieder das alte Problem der Suche in einem Benutzerprofil in DotNetNuke..... zuerst sah die ganze Geschichte noch recht brauchbar aus, allerdings wird das unter "Druck" ziemlich langsam. Eine Suchanfrage dauert da schon mal 8 Sekunden und das um gerade mal 10 - 15 Datensätze zu ermittlen. Ich finde das ist nicht akzeptable, zumal ich jetzt noch mit keiner großen Datenmengen > 30.000 arbeite. Also hat sich mein Verdacht bestätigt, dass die Lösung einfach nicht performant genug ist. Das ermittlen der benötigten PLZ geht recht schnell, nur leider dann das zerpflücken der Daten aus der Tabelle ASPNET_PROFILE dauert und dauert. Nun hier kann man aber dem guten SQL-Server keine Schuld geben, für das was dort passiert ist er immer noch verdammt gut  ;-) Na jetzt muss aber eine andere Lösung her damit DotNetNuke bzw. meine Lösung hier etwas mehr Spaß macht! Meine Idee ist jetzt einfach mit einer redundanten Tabelle zu arbeiten, in denen ich die Daten aus der Tabelle ASPNET_PROFILE speichere. Um aber dafür nichts im Core-Bereich zu modifzieren, werde ich versuchen die Daten via Trigger in die neue Tabelle zu schreiben. Ob mir das geklingt und wie das wird .. na klar, gibt es hier auf dieser Welle!

Stored Procedure "WHERE IN" Parameter übergeben

Wie kann man an eine Strored Procedure eine List übergeben, die für einen WHERE Part benötigt werden. WHERE PLZ IN '22222','22222' Zunächst unterstützen Stored Procedure keine Array's, deswegen muss man ein wenig tricksen. Create Procedure Gibmaluser @sParamList nvarchar(400) AS    DECLARE @sqlStr nvarchar(4000) @sqlStr = 'SELECT * FROM Meiner_Tabelle WHERE Name In (' +  @sParamList + ')'EXEC @sqlStr go Um diese SP nun aufzurufen muss man dann lediglich folgendes machen: sp_GetVendorsByList '''1'',''2'',''3''' Die ganze Geschichte brauche ich, wie sollte es auch anders sein, für DotNetNuke und der Suche nach Benutzernprofilen. PS:Das ist natürlich jetzt kein Hexenwerk und man findet schon jede Menge Stuff darüber bei google, aber ich gebe doch so gerne auch meine Senf dazu ;-)

Oracle hat eine neue Website für .NET Entwickler

Das Oracle Technology Network hat eine neue Webseite mit dem Namen ".NET Developer Center" online gestellt. Hier gibt es alle wichtigen Informationen für die Entwicklung von .NET-Anwendungen, die Oracle-Datenbanken nutzen. Um optimal mit einer Oracle-Datenbank zusammen zuarbeiten gibt es ein Visual Studio Plug-In zum freien Download. http://www.oracle.com/technology/tech/dotnet/

Microsoft SQL Server 2005 für verschiedene Kundensegmente

Die neue Version des MS SQL Servers wird für verschiedene Anforderungen der Kunden verfügbar sein. Microsoft hat eine Unterteilung in vier Gruppen vorgenommen und will damit jede Zielgruppe optimal bedienen: SQL Server 2005 Enterprise Edition: komplette Daten- und Analyseplattform für umfangreiche Unternehmensanwendungen SQL Server 2005 Standard Edition: komplette Daten und Analyseplattform speziell für mittelständische Unternehmen SQL Server 2005 Workgroup Edition: preisgünstigere und einfach zu handhabende Datenbank-Lösung für die Ansprüche kleiner und mittelständischer Unternehmen SQL Server 2005 Express Edition: kostenlose, einfach zu handhabende Version, die für den Aufbau von einfachen datengestützten Anwendungen entwickelt wurde Mehr Informationen findet man unter: http://www.microsoft.com/sql/

XML in SQL Server 2005

Microsoft bietet in den nächsten Tagen mal wieder eine Reihe von Webcast zum Thema MS SQL Server 2005. Themen dabei sind: Was gibt es neues für den Entwickler T-SQL-Erweiterungen im SQL Server 2005 XML in SQL Server 2005 Stored Procedures, Funktionen und Aggregationen mit .NET User Defined Types ADO.NET 2.0 und SQL Server 2005 Integration Services Einführung in den SQL Server Service Broker Das neue Sicherheitsmodell Analysis Services für Entwickler Volltextsuche in SQL Server 2005 Replikation mit SQL Server 2005 Termine und weiter Infos findet man unter:https://www.microsoft.com/germany/msdn/webcasts/kuenftige.aspx  

Opensource Projekt -> Firebird - Anbindung

Da es für Dotnetnuke mittlerweile nur noch einen Datenbankprovider gibt, wäre es doch sehr schön weiter kostenlose Alternativen zu schaffen. Aus diesem Grund hat sich in den letzten Tagen eine Gruppe zusammengefunden, die sich nun mit der Erstellung allternativer Datenbankprovider beschäftigt.Derzeit besteht das Team aus drei Leuten - Tom www.dbresource.de, Hans-Peter www.dnnportal.de und meiner Person. Bin sehr gespannt wie sich das weiterentwickelt. Die ersten Schritte sind auf jeden Fall gemacht. Wäre doch schön, wenn DotNetnuke nicht nur mit dem MS SQL-Server sondern auch mit Firebirdsql oder MySQL zusammenarbeiten würde .... Mehr in den nächsten Tagen!

MSDE ein alter Hut - oder besser Tipps & Tricks

Jedes mal ist es der selber Ärger, das Notebook geht Platt und das letzte Image ist zwar super .. aber in paar Kleinigkeiten fehlen dann halt doch. So suche ich immer wieder wie ein blöder nach zwei ganz simplen Einstellungen der MSDE. Diese sind einfach zu simple um sie zu behalten. Zunächst das Ändern des SA-Passwortes: in das Verzeichnis C:\Programme\Microsoft SQL Server\80\Tools\Binn wechseln den Befehl "osql -E sa" ausführen sp_password @old = null, @new= 'PASSWORT' , @loginame = 'sa' eingeben "Enter" um die Eingabe abzuschicken. "go" und Enter eingeben um den Befehl auszuführen. Ein zweites Problem gibt es mit der Einstellung "Login-Mode"; also WindowsNT oder Mixed Mode. Dafür gibt es in der Registry einen Key, den man setzen muss: HKEY_LOCAL_MACHINE\SoftWare Microsoft\MSSQLServer\MSSQLServer -> LoginMode = 1 (Windows NT) oder LoginMode = 2 (Mixed Mode) Nun gibt es beide Einstellungen mal endlich zusammen auf einer Seite!