Freitag, 9. Dezember 2011

ExPEditor - Editor for SQL Server Extended Properties

Mit dem Artikel möchte ich auch was zum Thema „Datenbankdokumentation“ beitragen, und zwar ein Tool ExPEditor vorstellen.


Zu einer Datenbankdokumentation gehören auf jeden Fall ein ER-Diagramm und eine technische und fachliche Beschreibung von Datenbankobjekten (Tabellen, Spalten, usw.). Die beiden Arten von der DB-Dokumentation kann man generieren lassen und es sind bereits ein oder anderes der kostenpflichtigen Tools, die es ermöglichen, bekannt.
SQL Server z.B. bietet Extended Properties zum Speichern der „fachlichen“ Beschreibung von Datenbankobjekten an. Es ist möglich, mehrere Extended Properties zu einem Datenbankobjekt hinzuzufügen. Die Extended Properties kann man direkt im SQL Server Management Studio editieren, es sind dafür leider mehrere Mouse-Klicks notwendig, bis man eine Eigenschaft editieren kann.

ExPEditor

Um die Arbeit mit Extended Properties zu vereinfachen und bequemer zu machen, habe ich die Entwicklung von dem ExPEditor gestartet und möchte heute eine Alpha-Version vorstellen.
Es sind folgende Features geplant
  • Navigation durch alle Datenbanken einer SQL Server Instanz
  • Bearbeitung von Extended Properties
  • Generieren von Beschreibung des Datenbankschemas im Word-Format
  • Generieren von DDL-Skripten zum Hinzufügen und Aktualiseren von Extended Properties
  • Anzeige von Definitionen der Datenbankobjekten

Implementierungsstand

Der ExPEditor ermöglicht ein bequemeren Zugriff auf die Extended Properties als das SQL Server Management Studio es anbietet
In der Alpha-Version kann man vorhandene Extended Properties und das Property Description, das automatisch durch ExPEditor zu jedem Objekt hinzugefügt wird und den Hauptteil der fachlichen Dokumentation darstellt, bearbeiten. In einer der nächsten Versionen wird es möglich sein, mehrere freibenannten EP’s zu einem Datenbankobjekt hinzuzufügen.
Das Generieren der Datenbankbeschreibung im Word-Format ist implementiert. Es gibt die Möglichkeit den Inhalt des Dokumentes nur für ausgewählte Datenbankobjekttypen generieren zu lassen.
Es kann ein DDL Skript generiert werden um alle Extended Properties einer Datenbank zu einer anderen Instanz zu übertragen.
Außerdem zeigt das Tool die DDL-Definition/T-SQL von Views, SP’s, Funktionen und Trigger an, was eine Datenbankentwicklung beschleunigen könnte und einem neuen Kollegen einen schnelleren Einstieg in die Entwicklung ermöglicht.

User Interface

Abbildung 1: Hauptfenster mit einem Objekt Explorer und einer tabellarischen Sicht, in der die Extended Properties des ausgewählen Objektes editiert werden können
 Abbildung 2: Ein zusätzliches Dialog zum Editieren von Extended Properties, ermöglicht bequemere Erfassen von mehrzeiligen Beschreibung
Abbildung 3: Dialog zum Auswahl von Datenbankobjekttypen, für die die Datenbankdokumentation im Word-Format generiert wird. Man kann im Dialog den Pfad zum Speichern des generierten Dokuments auswählen. Wenn die Checkbox "Save and Open" markiert ist, wird das generierte Dokument im Word automatisch geöffnet.
Abbildung 4: Definition einer gespeicherten Prozedur

Technischen Voraussetzungen

Für Verwendung des ExPEditor's müssen Microsoft Word ab 2007 und .Net Framework 4.0 auf dem Rechner installiert sein.

Anmerkung

Der ExPEditor wird kostenfrei zur Verfügung gestellt und von mir weiterentwickelt. Ich freue mich auf jede Rückmeldung, die man an die E-Mail im About-Dialog des ExPEditor's senden kann.

Download

Dienstag, 21. Juni 2011

CountDistinct (T-SQL)

Möchte man Anzahl von eindeutigen Werten ermitteln, kann man das Argument DISTINCT der Funktion COUNT dazu verwenden.
Hier ist ein Beispiel
use tempdb
go

create table t1
(
 col1 int null
)
go

insert into t1 values
(1),(2),(3),(4),(5),
(1),(2),(3),(4),
(1),(2),(3),
(1),(2),
(1),
(null)
go

select
 count(distinct col1) as CountDistinct,
 count(all col1) as CountAll,
 count(*) as CountAsterisk
from t1
go

drop table t1
go
Hier ist das Resultset
CountDistinct CountAll    CountAsterisk
------------- ----------- -------------
5             15          16

Sonntag, 5. Juni 2011

Versionsnummer einer Datenbank

Bevor man First-Level-Support anruft, sollte man zumindest die Versionsnummer des Beschwerdeobjekts kennen, um die Hilfe schnell und gezielt zu bekommen.
Bei Assemblies z.B. ist es üblich, Versionsnummer in Assembliesinfo zu verpacken, Oberflächen besitzen eigene Dialogboxen oder Seiten About, um die Versionsinfo dem Anwender zur Verfügung zu stellen.
Was ist mit Datenbanken, muss man eine Datenbank mit einer Versionsnummer versehen? Wird eine Datenbank nur von einer Anwendung verwendet, kann man in einigen Fällen die Datenbank und die Anwendung unter einer Versionsnummer zusammen ausliefern, dann wird das About-Anwendungsfenster ausreichend sein. Bei Enterprise-Lösungen wird eine Datenbank von „zich“ Web- und Windows-Services, Enterprise Service Bus, Web- und Desktop- Anwendungen verwendet, dazu kommen noch ETL-Prozesse, BI-Lösungen, die die Datenbank als Ziel oder Datenquelle anbinden. Mit anderen Wörtern wird eine Datenbank in einer Enterprise Lösung als einzelne Komponente betrachtet, deren Aktualisierung nicht zwingend eine Aktualisierung von anderen Komponenten der Gesamtlösung erfordert. Es ist auch umgekehrt gültig, beim Bugfixing einer Middleware-Anwendung wird die Datenbank nicht neu bereitgestellt, daher bleibt sie unter einer anderen Version bestehen.
Also ja, man sollte eine Datenbank mit einer Versionsnummer versehen. Die Frage ist „Wie?“.
Man könnte eine Tabelle Version erstellen, in der die ganze Versionsinfo abgespeichert wird. Es gibt aber für SQL Server Datenbanken (ab SQL Server 2005) auch eine andere Möglichkeit, die ich persönlich viel eleganter finde als eine Version-Tabelle. Die Möglichkeit ist, erweiterte Eigenschaften einer Datenbank und Datenbankobjekten einzusetzen. Im Beispiel 1 zeige ich, wie Datenbankeigenschaften um die Version und Bereitstellungsinfo erweitert werden können. Die erweiterten Eigenschaften einer Datenbank sind in SQL Server Management Studio über das Fenster Database Properties und die Seite Extended Properties zu erreichen (s. Abbildung 1).
Möchte man die erweiterten Eigenschaften von einer Anwendung aus abfragen, steht die Funktion fn_listextendedproperty zu Verfügung, ein Einsatz der Funktion ist auch in dem Beispiel 1 zu finden.
Beispiel 1: Erstellen von erweiterten Eigenschaften Version, Last deployment, Deployed by der aktuellen Datenbank
-- Stored Procedure
-- dbo.merge_extended_db_property
-- erstellt oder aktualisiert erweiterte Eigenschaften
-- der aktuellen Datenbank
-- @name - Name der Eigenschaft
-- @value - Wert der Eigenschaft
create proc dbo.merge_extended_db_property
 @name sysname,
 @value sql_variant
as
begin
 if not exists
 (
  select name
  from
   fn_listextendedproperty(@name,
     default, default, default,
     default, default, default)
 )
 begin
  exec sys.sp_addextendedproperty @name, @value
 end
 
 exec sys.sp_updateextendedproperty @name, @value
end
go
 
-- Erweiterte Eigenschaft 'Version'
-- Version der bereitgestellten Datenbank 
declare @name sysname = N'Version'
declare @value varchar(16) = '1.3.25'
exec dbo.merge_extended_db_property @name,@value
go

-- Erweiterte Eigenschaft 'Last deployment'
-- Das Datum der Bereitstellung der Datenbank
declare @name sysname = N'Last deployment'
declare @value varchar(128) = convert(varchar(128),getdate(),121)
exec dbo.merge_extended_db_property @name,@value
go

-- Erweiterte Eigenschaft 'Deployed by'
-- Anmeldename des Benutzers,
-- der die Datenbank bereitgestellt hat
declare @name sysname = N'Deployed by'
declare @value varchar(128) = system_user
exec dbo.merge_extended_db_property @name,@value
go
-- Löscht die Prozedur dbo.merge_extended_db_property
drop proc dbo.merge_extended_db_property
go
Abbildung 1: Anzeigen erweiterter Eigenschaften in SSMS


Verwandte Links

Sonntag, 29. Mai 2011

Tabellen vor versehentlichem Löschen schützen

Ich kann mich an einige Fälle erinnern, als Produktionsdatenbanken aus einem Versehen oder fehlender Übersicht der Infrastruktur verschrottet wurden. Es fängt mit dem Löschen einer Tabelle an und endet mit der Bereitstellung einer nicht getesteten Version der DB auf dem Produktionssystem. Dazu gibt es noch Benutzertabellen in der SQL Server Systemdatenbanken, die eigentlich nicht dahin gehören.

Könnte man die Fälle vermeiden oder das Risiko zumindest reduzieren?

Als erste Maßnahme soll man die Sicherheit der SQL Server Umgebung konzipieren und den Kreis der Mitarbeiter reduzieren, die zu der Serverrolle sysadmin und der Datenbankrolle dbo (databaseowner) zugeordnet sind.

Leider lässt es sich nicht in allen Projekten und nicht bei allen Kunden vermeiden, dass die sa- oder dbo-Berechtigungen für viele zugänglich sind. Außerdem können die Fehler auch einem erfahrenen Entwickler oder Administrator passieren.

Ich habe in einem Buch den Vorschlag gelesen, View‘s mit der Option SCHEMABINDING zu erstellen um das Löschen der zugrunde liegenden Tabellen zu unterbinden. Die aus einer View referenzierten Tabellen können nur nach einem Löschen der View gelöscht werden. Das Beispiel 1 zeigt, wie es umgesetzt werden könnte.

Beispiel 1: Schutz einer Tabelle vor versehentlichem Löschen mit einer schemagebundenen View
use [Insidesql.org]
go
create table dbo.MyTable
(
    MyTableID int identity,
    Col1 nvarchar(55)
)
go
create view dbo.vwMyTable
    with schemabinding
as
select
    MyTableID,
    Col1
from
    dbo.MyTable
go
-- Den folgenden Versuch, die Tabelle dbo.MyTable zu löschen,
-- beenden mit der Fehlermeldung:
-- Msg 3729, Level 16, State 1, Line 1
-- Cannot DROP TABLE 'dbo.MyTable' because it is being referenced by object 'vwMyTable'.
drop table dbo.MyTable
go
-- Um die Tabelle löschen zu können, muss zuerst die View dbo.vwMyTable gelöscht werden.
drop view dbo.vwMyTable
drop table dbo.MyTable
go
Tatsächlich kann man View's mit SCHEMABINDING als Schutz vor einem Löschen der Tabellen nutzen, aber ich persönlich bevorzuge, einen DDL-Trigger einzusetzen. Beispiel 2 zeigt, wie man mit einem DDL-Trigger das Erstellen, Ändern und Löschen aller Tabellen der Datenbank unterbinden kann. Es gibt sogar weitere Möglichkeiten mit einem DDL-Trigger Functions, Stored Procedures und andere Datenbankobjekte vor einem Löschen zu schützen. Ein Überblick über die DDL-Ereignisgruppen, die einen DDL-Trigger ausführen, bekommt man in dem MSDN Artikel DDL-Ereignisgruppen.

Beispiel 2: DDL-Trigger als Überwachung der Datenbankänderungen
use [Insidesql.org]
go
create table dbo.MyTable
(
    MyTableID int identity,
    Col1 nvarchar(55)
)
go
if exists
(
    select *
    from sys.triggers
    where name = N'TR_TABLE_DENY_CAD'
        and parent_class_desc = N'DATABASE'
)
drop trigger TR_TABLE_DENY_CAD on database
go

create trigger TR_TABLE_DENY_CAD on database 
    for CREATE_TABLE, ALTER_TABLE, DROP_TABLE 
as 
begin
    print 'You must ask your DBA to create, alter or drop tables!' 
    rollback transaction
end
go

-- Den folgenden Versuch, die Tabelle dbo.MyTable zu löschen
-- beenden mit der Fehlermeldung:
-- You must ask your DBA to create, alter or drop tables!
-- Msg 3609, Level 16, State 2, Line 1
-- The transaction ended in the trigger. The batch has been aborted.
drop table dbo.MyTable
go
Vorteile der DDL-Trigger-Lösung
  • In einem DDL-Trigger können mehrere Typen von DDL-Ereignissen unterbunden werden
  • Es können mehrere DDL-Trigger für unterschiedliche DDL-Ereignisse erstellt werden
  • Ein DDL-Trigger überwacht alle Objekte der DDL-Ereignisgruppe, damit ist keine Anpassung des Triggers notwendig, wen z.B. eine Tabelle umbenannt oder gelöscht wird
  • Es ist kein Löschen des DDL-Triggers notwendig, wenn die DDL-Ereignisse zugelassen werden müssen, für die der Trigger erstellt ist. Es reicht den DDL-Trigger zu deaktivieren
  • DDL-Trigger's sind von anderen Datenbankobjekten getrennt gespeichert und damit leicht zugänglich
Aktivieren und Deaktivieren vom DDL-Trigger
Wird ein DDL-Trigger zum Schützen von Datenbankobjekten vor versehentlichem Löschen eingesetzt, sollte man den Trigger vor der Bereitstellung der Datenbank per Hand über das SSMS (siehe Abbildung 1) in der Zieldatenbank deaktivieren. Um den Trigger nach der Bereitstellung automatisch zu aktivieren, kann man am Ende des Bereitstellungsskripts den folgenden Befehl einbauen:
enable trigger TR_TABLE_DENY_CAD on database
go
Abbildung 1: Deaktivieren von DDL-Trigger

Zusammenfassung
Man kann das Risiko einer versehentlichen Änderung einer Datenbank reduzieren, indem:
  • die Datenbankberechtigungen sorgfältig verteilt werden
  • Standarddatenbank von SQL Server-Anmeldungen gepflegt wird
  • use-Anweisung in Bereitstellungsskripten benutzt wird
  • schemagebundene View’s oder DDL-Trigger’s implementiert werden.

Donnerstag, 26. Mai 2011

PRIMARY KEY-Einschränkungen mit einem NONCLUSTERED INDEX finden

In der Regel verfügt eine Tabelle über PRIMARY KEY-Einschränkung, für die ein gruppierter Index standardmäßig erstellt wird. Man kann auch eine PK-Einschränkung mit einem nicht gruppierten Index erstellen. Als ein Beispiel dafür siehe Abfrage 3.
Sind die Richtlinien für den Entwurf gruppierter Indizes angehalten, ist der Index eine gute Grundlage für die Erstellung von weiteren Indizes und so für eine schnellere Datenbank.
Entwickelt oder optimiert man eine große Datenbank, kann es passieren, dass gruppierte Indizes für eine ungünstige Spalte oder Spaltenkombination erstellt werden. Besonders teuer für Abfragen können die Tabellen mit einer PRIMARY KEY-Einschränkung sein, für die ein nicht gruppierter Index oder ein gruppierter Index für die Spalten, die nicht in die PK eingeschlossen sind, erstellt wurde. Deswegen sollte man die Tabellen genauer anschauen.
Um einen Überblick über die PRIMARY KEY-Einschränkungen mit einem nicht gruppierten Index  in einer großen Datenbank zu bekommen, habe ich die folgenden zwei Abfragen geschrieben.
Abfrage 1. Bezeichnet Tabellennamen mit 1, die einen gruppierten Index besitzen
select
    name as TableName,
    objectproperty(t.object_id,'TableHasClustIndex')
        as HasClustIndex
from
    sys.tables t
go
Abfrage 2. Bezeichnet PK-Einschränkungen mit 1, für die ein gruppierter Index erstellt wurde
select
    quotename(schema_name(k.schema_id)) + '.' +
    quotename(object_name(k.parent_object_id)) as TableName,
    k.name as PrimaryKey,
    objectproperty(k.[object_id],'CnstIsClustKey') as IsClustKey
from
    sys.key_constraints k
where
    k.[type] = 'PK'
order by
    k.schema_id ,k.parent_object_id
go
Abfrage 3. Erstellt die PK-Einschränkung [PK_MyTable] für die Tabelle [MyTable] mit einem nicht gruppierten Index
create table dbo.MyTable
(
    MyTableID int identity,
    Column1 nvarchar(55),
    constraint PK_MyTable primary key nonclustered
    (
        MyTableID
    )
)
go

oder

create table dbo.MyTable
(
 MyTableID int identity constraint PK_MyTable primary key nonclustered,
 Column1 nvarchar(55)
)
go
Verwandte Links:

Sonntag, 22. Mai 2011

Reflektion (.Net)

Verwendung von Reflektion erhöht die Flexibilität der Entwicklung einer Anwendung. Mit Hilfe von Reflektion können Metadaten des Programms abgefragt, Typen der Assembly zur Laufzeit gefunden und dynamisch instanziiert, Methoden eines vorhandenen Objekts aufgerufen werden.
Mike Repass untersucht  in dem Artikel Reflexionen über Reflektion den System.Reflection-Namespace und  seine Einsatzmöglichkeiten im Entwicklungsprozess.
Verwandte Links:

Sonntag, 20. März 2011

SQL Server Profiler: gruppieren von Ereignissen

Der SQL Server Profiler leistet eine große Hilfe bei der Optimierung von Datenbanklösungen. Mit dem Tool kann man Ablaufverfolgungen konfigurieren, starten, beenden und aufgezeichnete Ereignisse analysieren.
Es gibt aber Fälle, wenn die Analyse trotz einer geringen Ereignisauswahl und Filtereinschränkung schwierig sein kann und man bei der Benutzung des Dialogs Find nicht vorankommt. In dem Fall sollte man versuchen die Ereignisse nach z.B. DatabaseName, ClientProcessID oder SPID zu gruppieren.
Gruppierung von Ereignissen einrichten
  1. Starten Sie den SQL Server Profiler
  2. Erstellen Sie eine neue Ablaufverfolgung
  3. Wählen Sie gewünschte Ereignisse und Ereignisspalten
  4. Klicken Sie im Fenster Trace Properties auf dem Reiter Events Selection den Knopf Organize Columns… an
  5. Im Fenster Organize Columns verschieben Sie eine Spalte in den Knoten Groups und klicken Sie auf dem Knopf OK

Damit ist die Gruppierung eingerichtet und die Ablaufverfolgung kann gestartet werden.
Aggregierte und gruppierte Sicht
Wenn eine Ablaufverfolgung ausgeführt, angehalten oder beendet wird, kann man immer zwischen aggregierten und gruppierten Sichten im Menü View umschalten (siehe Bild unten).

Eine aggregierte Sicht ermöglicht Zusammenklappen und Aufklappen von allen Ereignissen einer Gruppe. Leider kann man die Sicht nur für die Gruppierung verwenden, die aus einer Spalte besteht.
In einer gruppierten Sicht werden Ereignisse gruppiert nach ausgewählten Spalten angezeigt. Die Sicht kann man für die Gruppierung verwenden, die aus einer oder mehreren Spalten besteht.
Gruppierung von Ereignissen anpassen
Falls eine beendete Ablaufverfolgung aus einer Datei oder Tabelle geöffnet wird, kann die Gruppierung beliebig angepasst werden.
Falls eine Ablaufverfolgung läuft, können die aufgezeichneten Daten neu gruppiert werden, indem die Ablaufverfolgung angehalten, die Gruppierung angepasst und die Ablaufverfolgung wieder gestartet wird.
Falls eine laufende Ablaufverfolgung beendet wird, die Gruppierung angepasst und die Ablaufverfolgung neu gestartet wird, gehen alle aufgezeichneten Daten verloren und die Gruppierung wird nur für die neu aufgezeichneten Daten übernommen.
Hinweis
Beachten Sie bei einer Gruppierung nach DatabaseName:
Wenn Ihre Anwendung mehrere Datenbanken verwendet und im Kontext einer DB die Daten aus einer anderen DB abgefragt werden, wird die Abfrage der DB zugeordnet, in deren Kontext sie ausgeführt wurde (siehe Bild).

Montag, 28. Februar 2011

SQL Server Agent Job Step Notification

SQL Server Agent bietet unter anderem E-Mail Benachrichtigungen für die Jobs an, die z.B. fehlschlagen. Aber für das ganze Job, nicht für die einzelnen Schritte. Wenn so eine E-Mail Benachrichtigung konfiguriert ist, kriegt man z.B. folgende Nachricht:
JOB RUN: 'name' was run on 14.10.2010 at 02:00:00
DURATION: 0 hours, 16 minutes, 4 seconds
STATUS: Failed
MESSAGES: The job failed. The Job was invoked by Schedule ** (name). The last step to run was step * (name).
Die Nachricht beinhaltet keine Info über den Fehler selber, obwohl ein Eintrag in die Tabelle msdb.dbo.sysjobhistory gemacht wird, wenn ein Jobstep fehlgeschlagen oder erfolgreich ausgeführt ist.
Es wäre günstiger, wenn man die detaillierte Info gekriegt hätte und sich die Anmeldung am System mit der Untersuchung des Fehlerprotokolls ersparen könnte, denn meistens kann die Fehlerursache aus der detaillierten Fehlermeldung ermittelt werden.
Als kleine Hilfe habe ich den folgenden Insert-Trigger der Tabelle msdb.dbo.sysjobhistory implementiert, der eine E-Mail an den beim Job eingetragenen Operator versendet, wenn die Benachrichtigungsbedingungen des Jobs erfüllt sind.
Wenn Sie den Trigger einsetzen möchten, tragen Sie einen gültigen Profilnamen der Database Mail im Trigger in der Variable @profile_name ein.
Alle konfigurierten Profile der Database Mail finden Sie in der Tabelle msdb.dbo.sysmail_profile.
use msdb
go
if exists (
select * from sys.triggers 
where object_id = object_id(N'[dbo].[TR_sysjobhistory_INS]'))
drop trigger [dbo].[TR_sysjobhistory_INS]
go

create trigger dbo.tr_sysjobhistory_ins
  on dbo.sysjobhistory
  after insert
as
begin
 set nocount on;

 declare @subject nvarchar(255)
 declare @body nvarchar(max)
 declare @message nvarchar(4000)
 declare @run_date varchar(10)
 declare @run_time int

 declare @profile_name sysname
 set @profile_name = 'hier profile_name eintragen'
 declare @recipients nvarchar(max)

 select
  @subject = (case h.run_status when 1 then 'Succeeded' else 'Failed' end)
  + ' [' + h.[server] + '].[' + j.[name] + '].[' + h.[step_name] + ']',
  @message = h.[message],
  @run_date = cast(convert(date,(cast(h.[run_date] as varchar(10))),120) as varchar(10)),
  @run_time = h.[run_time],
  @recipients = o.email_address
 from
  inserted h
  inner join msdb.dbo.sysjobs j
  on h.job_id = j.job_id
  left join msdb.dbo.sysoperators o
  on j.notify_email_operator_id = o.id
 where
  ((h.[run_status] = 0 and j.notify_level_email = 2)
  or (h.[run_status] = 1 and j.notify_level_email = 1))
  and j.notify_level_email > 0
  and h.step_id > 0

 if (@subject is not null)
 begin
  declare @crlf char(2)
  set @crlf = char(13) + char(10)
  declare @pos tinyint = (case when @run_time > 95959 then 3 else 2 end)
  set @body = 'RUN STEP: ' + cast(convert(date,@run_date, 120) as varchar(10)) + 
  ' ' + stuff(stuff((cast(@run_time as varchar(32))),@pos,0,':'),@pos+3,0,':')
  set @body = @body + @crlf
  set @body = @body + 'MESSAGE: ' + @message
  
  exec msdb.dbo.sp_send_dbmail
   @profile_name = @profile_name,
   @recipients = @recipients,
   @body = @body,
   @subject = @subject;
 end
end
go

Samstag, 29. Januar 2011

SQL Server Agent Job automatisch löschen

Möchten Sie einmalig und eingeplant z.B. eine gespeicherte Prozedur aufrufen und dabei administrativen Aufwand reduzieren, könnte für Sie die Option Automatically delete job nützlich sein.
Falls Sie das SQL Server Management Studio für Erstellung eines Jobs verwenden, klicken Sie auf Notifications, aktivieren Sie Automatically delete job und wählen Sie eine von drei Bedingungen aus, bei der der Auftrag zu löschen ist.


Falls Sie den Job mit T-SQL erstellen, verwenden Sie das Argument @delete_level der Systemprozedur sp_add_job. @delete_level nimmt folgende int-Werte an: 0-nie(Standardwert), 1-bei Erfolg, 2-bei Fehler, 3 – immer.

Nachdem der Auftrag ausgeführt wurde und dabei sein Status mit dem delete_level übereinstimmt, führt der Job Manager die Anweisung aus:
EXEC msdb.dbo.sp_delete_job @job_id = job_id

Sonntag, 16. Januar 2011

SQL Server sa Passwort

Suchen Sie ein Standard Passwort des sa Logins, weil die SQL Server Zugangsdaten verloren gegangen sind? Finden Sie keins! ;) Ich beschreibe hier, wie Sie das Problem umgehen könnten.
Besitzen Sie keine Zugangsdaten zum SQL Server, aber Administratorberechtigungen auf dem Rechner, wo SQL Server Instanz installiert ist, besteht noch die Möglichkeit die SQL Server Instanz mit Sysadmin Berechtigungen im Einzelbenutzermodus anzubinden.
Gehen Sie die unten beschriebenen Schritte durch, um aus der unangenehmen Situation herauszukommen:
  • Öffnen Sie SQL Server Configuration Manager
  • Klicken Sie auf dem Knoten SQL Server Services
  • Halten Sie den Dienst des SQL Server Agents an
  • Öffnen Sie Eigenschaften des Dienstes der SQL Server Instanz
  • Fügen Sie zu den Startparametern des Dienstes den Parameter –m hinzu, um SQL Server Instanz im Einzelbenutzermodus zu starten
  • Starten Sie den Dienst der SQL Server Instanz neu
  • Stellen Sie eine Verbindung zur SQL Server Instanz her (z.B. in SSMS)
  • Erstellen Sie ein Benutzerkonto und fügen Sie es zu der Serverrolle Sysadmin hinzu
  • Entfernen Sie den Parameter –m von den Startparametern des SQL Server Dienstes
  • Starten Sie den Dienst der SQL Server Instanz neu
  • Starten Sie den Dienst des SQL Server Agents
Best practices für sa Login:
  • Nutzen Sie nur sichere Passwörter.
  • Ändern Sie das Passwort des sa Logins regelmäßig.
  • Verwalten Sie SQL Server Instanz unter dem sa Konto nie.
  • Benennen Sie den sa Login um.