maandag 17 november 2008

Installatie Windows Server 2003 R2 met SP1 voor clustering

Installatie Windows Server 2003 R2 met SP1 voor clustering

{ tekst } = opdracht in tekst (voor gebruik in CMD.EXE)
< tekst > = variabele (uiteindelijk invoeren zonder < >)
‘ tekst ’ = AD rechten
“ tekst “ = tekst in te voeren in een invoerveld
[ tekst ] = aan te klikken knop of menu item in een scherm

1. Maak een cluster service account aan binnen het domein zonder password expiration
2. Zorg dat het cluster service account local administator is op alle cluster nodes
3. Zorg dat het cluster service account rechten heeft om groepslidmaatschap van groepen te veranderen voor de service accounts van SQL Server
4. Pas de domain policy aan voor het service account van het cluster, zodat deze de volgende rechten heeft op alle cluster nodes
a. ‘Manage auditing and security log’
5. Kopieer de source files van Windows Server 2003 en SQL Server 2005 naar D:\Install op alle nodes
6. Disconnect alle netwerk drives in de verkenner op alle nodes
7. Pas de local policy aan voor de service accounts op alle nodes
a. ‘Act as part of the operating system’
b. ‘Bypass Treverse Checking’
c. ‘Lock pages in memory’
d. ‘Log on as a Batch Job’
e. ‘Log on as a Service’
f. ‘Replace a process level token’


8. Voer met diskpart de volgende commando’s uit voor elke shared schijf op slechts één van de nodes
a. {SELECT DISK }
b. {CREATE PARTITION PRIMARY ALIGN=64}
c. {ASSIGN LETTER=}
9. Formatteer elke schijf met een cluster grootte van 64kb op slechts één van de nodes
10. Configureer IIS op alle nodes, afbeeldingen in bijlage A
a. [Start], [Control Panel], [Add or Remove Programs], [Add/Remove Windows Components]
b. Selecteer [Application Server] en klik op [Details]
c. Selecteer [Enable Network DTC Access] en verwijder [Application Server Console]
d. Selecteer [Internet Information Services] en klik op [Details]
e. Selecteer [Background Intelligent Transfer Services (BITS)]
f. Selecteer [World Wide Web Service] en klik op [Details]
g. Selecteer [Active Server Pages] en [Server Side Includes] en klik op [Ok], [Ok], [Ok] en [Next]
h. Geef het pad naar de installatie directory aan met [Browse], [Open] en klik op [Ok]
i. Klik op [Finish]



11. Configureer cluster node 1 (de node waar de schijven op geconfigureerd en geformatteerd zijn), afbeeldingen in bijlage B
a. Start cluster administrator [Start], [Administrative Tools], [Cluster Administrator] en connect niet naar een cluster, klik op [Cancel]
b. Klik op [File], [New], [Cluster], [Next]
c. Voer clusternaam in en klik op [Next]
d. Check computername en klik op [Next]
e. Omgeving wordt ge-analyseerd, bij ok (groene balk) klik op [Next]
f. Voer het IP adres van het cluster in en klik op [Next]
g. Voer de inlognaam, het wachtwoord en de domeinnaam in van het cluster service account en klik op [Next]
h. Klik op de knop [Quorum] en kies daar voor de “Q-Schijf” en klik op [Ok] en vervolgens op [Next]
i. Indien het creeeren van het cluster gereed is (groene balk) klik dan op [Next]
j. Klik vervolgens op [Finish]
12. Configureer cluster node 2
a. Klik in cluster administrator op [File], [New], [Node] en vervolgens op [Next]
b. Voer de naam van de tweede cluster node in en klik op [Add] en vervolgens op [Next]
c. Omgeving wordt ge-analyseerd, bij ok, (groene balk) klik op [Next]
d. Voer het wachtwoord van het cluster service account in en klik op [Next]
e. Controleer de configuratie en klik op [Next]
f. Indien het toevoegen van de cluster node gereed is (groene balk) klik dan op [Next]
g. Klik vervolgens op [Finish]
13. Check of de resource groups op alle nodes online komen en of ze weer terug op de eerste node komen
14. Pas de link speed aan op allen netwerkkaarten aan van [Automatic] naar [100Mb Full Duplex]
15. Voer één voor één een herstart uit van de alle nodes en check of de cluster resources netjes op de andere node online komen
16. Plaats alle schijven voor SQL in 1 Resource Group
17. Rename de Resource Group voor [MSDTC] naar [MSDTC Group]
18. Maak een IP Resource aan voor MSDTC
19. Maak een Network Name Resource aan voor MSDTC, afhankelijk van de MSDTC-IP Resource
20. Maak de service resource aan voor MSDTC, Afhankelijk van de Network Name en Schijf Resource
21. Test MSDTC Resource op alle nodes




Bijlage A: - Afbeeldingen configuratie Windows
[Start], [Control Panel], [Add and Remove Programs]



Bijlage A: - Afbeeldingen configuratie Clustering

Installatie SQL Server 2005 op een geclusterde omgeving

Installatie SQL Server 2005 op een geclusterde omgeving

{ tekst } = opdracht in tekst (voor gebruik in CMD.EXE)
< tekst > = variabele (uiteindelijk invoeren zonder < >)
‘ tekst ’ = AD rechten
“ tekst “ = tekst in te voeren in een invoerveld
[ tekst ] = aan te klikken knop of menu item in een scherm
1. Keuze voor versie SQL Server 2005
a. Developer versie voor alle niet productie omgevingen, Acceptatie, Test en Development (1 licentie voor elke gebruiker, ~ 60 euro per licentie)
b. Enterprise versie voor alle geclusterde productie omgevingen (1 licentie per processor, ~ 22.500 euro per processor, quad core processor geldt als 1 processor)
c. Standaard versie voor alle niet geclusterde productie omgevingen die geen hoge performance eisen hebben (1 licentie per processor, ~ 6.000 euor per processor, quad core processor geldt als 1 processor)
2. Maak een aantal service accounts aan als gewone domain users zonder extra rechten op de SQL Server Cluster nodes
a. “Svc_AwsSQLService” - SQL Server Service account
b. “Svc_AwsSQLSAS” - SQL Server Analysis Service account
c. “Svc_AwsSQLSAgs” - SQL Server Agent Service Account
d. “Svc_AwsSQLSB” - SQL Server Browser Service Account
e. “Svc_AwsSQLSRS” - SQL Server Reporting Service Account
3. Maak vier domein groepen aan t.b.v. de SQL Server installatie per cluster
a. “BINCK\DL_Appl_SQLServer_INSA01” - SQL Server groep
b. “BINCK\DL_Appl_SQLServerAgent_INSA01” - SQL Agent groep
c. “BINCK\DL_Appl_SQLFullTextService_INSA01” - SQL Full Text Search groep
d. “BINCK\DL_Appl_SQLAnalysisService_INSA01” - SQL Analysis groep
4. Log in op de eerste node met behulp van het Cluster Service Account
5. Start de setup vanaf de cd/dvd of netwerkshare
6. In het scherm [End User License Agreement] vink [I accept the licensing terms and conditions] aan en klik op [Next]
7. In het scherm [Installing Prerequisites] klik op [Install]
8. Als de prerequisites geinstalleerd zijn klik op [Next]
9. In het scherm [Welcome to the Microsoft SQL Server Installation Wizard] klik op [Next]
10. Controleer het scherm [System Configuration Check] op fouten of meldingen en klik op [Next]
11. In het scherm [Registration Information] vul het “Naam” en “Company” veld in en klik op [Next]
12. Vervolgens alles aanvinken in het scherm [Components to Install] (Niet op [Next] klikken!)
a. [SQL Server Database Services]
1. [Create a SQL Server failover cluster]
b. [Analysis Services]
1. [Create an Analysis Server failover cluster]
c. [Reporting Services]
d. [Notification Services]
e. [Integration Services]
f. [Workstation components, Books Online and development tools]
13. Klik nu op [Advanced] (niet op [Next])
14. Pas de diverse locaties aan voor de diverse onderdelen (zie afbeeldingen bijlage A)
a. Database Services op {D:\Microsoft SQL Server}
1. Data Files op {E:\Microsoft SQL Server}
2. Shared Tools op {D:\Microsoft SQL Server}
b. Analysis Services op {D:\Microsoft SQL Server}
1. Data Files op {E:\Microsoft SQL Server}
2. Shared Tools op {D:\Microsoft SQL Server}
15. In het scherm [Instance Name] klik op [Named instance] en vul daar de instance naam in en klik op [Next]
16. Vervolgens dient de Virtual server name ingegeven te worden in het scherm [Virtual Server name] en klik op [Next]
17. Bij [Virtual Server Configuration] dient aangegeven te worden welk netwerk gebruik dient te worden voor communicatie met de clients en het te gebruiken IP adres voor deze virtuele server, vul deze in, klik op [Add] en klik op [Next]
18. In het scherm [Cluster Group Selection] geef je de SQL Server resource group op en de locatie van de [Data Files] en klik je op [Next]
19. Vervolgens dien je aan te geven in [Cluster Node Configuration] welke nodes nog meer gebruikt moeten kunnen worden door deze virtuele server (als backup van de node waarop je installeert, dit kunnen er meerdere zijn, als het cluster uit meer dan twee nodes bestaat). Selecteer de node, klik op [Add] en vervolgens op [Next]
20. Om de installatie op alle nodes goed plaats te laten vinden dient er geinstalleerd te worden met een domain account dat local administrator is op alle nodes van het cluster. Vul deze gegevens in en klik op [Next]
21. De Service accounts welke aangemaakt zijn in stap 2 dienen nu ingevuld te worden in het scherm [Service Account]. Vink [Customize for each service account] aan en selecteer een voor een de services in [Service] en vul de inlognamen, wachtwoorden en domein namen in voor elke service. Klik daarna op [Next]
22. Het scherm [Domain Groups for Clustered Services] vraagt om de domain group’s welke in stap 3 zijn aangemaakt. Vul deze in en klik op [Next]
23. Als het Cluster Service Account niet de benodigde rechten heeft gekregen binnen AD (zie stap 2 in het document “Installatie en configuratie Windows Server 2003 R2 met SP1 voor clustering.doc) dan komt nu een foutmelding welke meldt dat er niet voldoende rechten zijn om accounts toe te voegen aan de in de vorige stap ingevulde groepen. Zorg dat het account waarmee je in bent gelogt deze rechten alsnog krijgt en klik op [Ok]. Installatie van SQL Server dient opnieuw gestart te worden.
24. In het scherm [Authentication Mode] dient [Mixed Mode] aangevinkt te worden en een password voor het “sa” account ingevuld te worden. Klik daarna op [Next]
25. In principe dient het scherm [Collation Settings] niet aangepast te worden, klik daarom op [Next]
26. In het scherm [Report Server Installation Options] klik je op [Next] zonder aanpassingen
27. [Error and Usage Report Settings] is het scherm waarin aangegeven wordt of fouten en gebruiksgegevens (anoniem en er wordt geen inhoudelijke data doorgestuurd) naar Microsoft gestuurd mogen worden. Microsoft kan hierdoor de producten verbeteren. Maak de juiste keuze hier en klik op [Next]
28. De setup wordt nu gestart en kan gevolgt worden in het scherm [Setup Progress], indien het klaar is, klik op [Next]
29. Klik op [Finish] in het scherm [Completing Microsoft SQL Server 2005 Setup]
30. Herstart alle nodes een voor een en check of alle resources online komen met behulp van de [Cluster Administrator] tool.


Installatie Service Pack 2
De installatie van een Service Pack is vergelijkbaar met het installeren van een Hot Fix Rollup. Deze tweede zal dus niet apart besproken worden, daarvoor komen de volgende stappen grotendeels overeen.
1. Log in met het Cluster Service Account (deze heeft local administrator rechten op alle nodes)
2. Start de SP2 executeable en klik op [Next] in het [Welcome] scherm
3. Klik op [I accept the agreement] en vervolgens op [Next] in het [License Terms] scherm
4. In het scherm [Feature Selection] vink alle onderdelen aan en klik op [Next]
5. Kies voor de default (Windows Authentication] en klik op [Next]
6. Ook voor de installatie van een Service Pack of Hot Fix installatie is een account nodig welke local administrator rechten heeft op alle nodes. Hier wordt het Cluster Service Account voor gebruikt omdat deze toch al local Administrator is. Vul de “Username”, “Password” en “Domain” in en klik op [Next]
7. [Error and Usage Report Settings] is het scherm waarin aangegeven wordt of fouten en gebruiksgegevens (anoniem en er wordt geen inhoudelijke data doorgestuurd) naar Microsoft gestuurd mogen worden. Microsoft kan hierdoor de producten verbeteren. Maak de juiste keuze hier en klik op [Next]
8. Het volgende scherm controleert of er bepaalde services actief zijn en dus voor een noodzakelijke reboot kunnen zorgen na de installatie van het Service Pack of Hot Fix. Er kan hier gewoon op [Next] geklikt worden, een reboot na installatie is aan te raden.
9. Nu is de setup klaar om te installeren [Ready to Install], klik hier op [Install]
10. De installatie wordt nu gestart en kan gevolgt worden in het scherm [Installation Progress], indien het klaar is, klik op [Next]
11. In het scherm [Installation Complete] klik op [Next]
12. In het scherm [Additional Information] dient het vinkje voor [Launch the User Provisioning Tool for Windows Vista after SP2 installation completes] niet aangevinkt te worden. Klik op [Finish]
13. Begin bij stap 1 voor de eventuele Post SP2 hotfix rollup updates met de executable van de hotfix rollup update in plaats van de SP2 executable

Aanpassen rechten structuur op schijf
De C, D en E schijven hebben als het goed is de rechten automatisch juist geplaatst gekregen voor de diverse domein groepen. Voor de overige schijven dienen de rechten overeenkomstig onderstaande gegevens aangepast te worden.
Abbreviations:
CI - Container Inherit. The ACE will be inherited by directories.
OI - Object Inherit. The ACE will be inherited by files.
IO - Inherit Only. The ACE does not apply to the current file/directory.
Folder
• Group or account Inheritance Rights
< driveletter>:\
• BUILTIN\Administrators: (OI)(CI) F
• NT AUTHORITY\SYSTEM: (OI)(CI) F
• CREATOR OWNER: (OI)(CI)(IO) F
• BUILTIN\Users: (OI)(CI) R
• BUILTIN\Users: (CI)(special access:) FILE_APPEND_DATA
• BUILTIN\Users: (CI)(IO)(special access:) FILE_WRITE_DATA
• Everyone: R
< driveletter >:\Microsoft SQL Server
• BUILTIN\Administrators: (OI)(CI) F
• NT AUTHORITY\SYSTEM: (OI)(CI) F
• BUILTIN\Administrators: F
• CREATOR OWNER: (OI)(CI)(IO) F
• BUILTIN\Users: (OI)(CI) R
• BUILTIN\Users: (CI)(special access:) FILE_APPEND_DATA
• BUILTIN\Users: (CI)(special access:) FILE_WRITE_DATA
< driveletter >:\Microsoft SQL Server\MSSQL.1
• BUILTIN\Administrators: (OI)(CI) F
• NT AUTHORITY\SYSTEM: (OI)(CI) F
• BUILTIN\Administrators: F
• CREATOR OWNER: (OI)(CI)(IO) F
• BUILTIN\Users: (OI)(CI) R
• BUILTIN\Users: (CI)(special access:) FILE_APPEND_DATA
• BUILTIN\Users: (CI)(special access:) FILE_WRITE_DATA
< driveletter>:\Microsoft SQL Server\MSSQL.1\MSSQL
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) R
• BUILTIN\Administrators: (OI)(CI) F
• NT AUTHORITY\SYSTEM: (OI)(CI) F
• BUILTIN\Administrators: F
• CREATOR OWNER: (OI)(CI)(IO) F

< driveletter>:\Microsoft SQL Server\MSSQL.1\MSSQL\Backup
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) F
• BUILTIN\Administrators: F
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) R
• BUILTIN\Administrators: (OI)(CI) F
• NT AUTHORITY\SYSTEM: (OI)(CI) F
• CREATOR OWNER: (OI)(CI)(IO) F
< driveletter>:\Microsoft SQL Server\MSSQL.1\MSSQL\Data
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) F
• BUILTIN\Administrators: F
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) R
• BUILTIN\Administrators: (OI)(CI) F
• NT AUTHORITY\SYSTEM: (OI)(CI) F
• CREATOR OWNER: (OI)(CI)(IO) F
< driveletter >:\Microsoft SQL Server\MSSQL.1\MSSQL\FTData
• BINCK\DL_Appl_SQLFullTextService_InsA01: (OI)(CI) F
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) F
• BUILTIN\Administrators: F
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) R
• BUILTIN\Administrators: (OI)(CI) F
• NT AUTHORITY\SYSTEM: (OI)(CI) F
• CREATOR OWNER: (OI)(CI)(IO) F
< driveletter >:\Microsoft SQL Server\MSSQL.1\MSSQL\JOBS
• BINCK\DL_Appl_SQLServerAgent_InsA01: (OI)(CI) F
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) R
• BUILTIN\Administrators: (OI)(CI) F
• NT AUTHORITY\SYSTEM: (OI)(CI) F
• CREATOR OWNER: (OI)(CI)(IO) F
< driveletter >:\Microsoft SQL Server\MSSQL.1\MSSQL\LOG
• BINCK\DL_Appl_SQLServerAgent_InsA01: (OI)(CI) F
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) F
• BUILTIN\Administrators: F
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) R
• BUILTIN\Administrators: (OI)(CI) F
• NT AUTHORITY\SYSTEM: (OI)(CI) F
• CREATOR OWNER: (OI)(CI)(IO) F
:\Microsoft SQL Server\MSSQL.1\MSSQL\repldata
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) F
• BINCK\DL_Appl_SQLServer_InsA01: (OI)(CI) R
• BUILTIN\Administrators: (OI)(CI) F
• NT AUTHORITY\SYSTEM: (OI)(CI) F
• CREATOR OWNER: (OI)(CI)(IO) F

Afhankelijkheden van cluster resources aanpassen
Als er meerdere data, index, log, backup en/of tempdb schijven zijn, dan dienen deze een afhankelijkheid ingesteld te krijgen voor de SQL Server Service resource. De volgende stappen beschrijven deze actie.
1. In Cluster Administrator selecteer de [SQL Server] resource group
2. Binnen de [SQL Server] resource group klik met de rechtermuisknop op de [SQL Server] resource en kies voor [Take Offline]
3. De [SQL Server Agent] resource gaat nu automatisch ook offline omdat deze een afhankelijkheid heeft van de [SQL Server] resource
4. Klik met de rechtermuisknop op de [SQL Server] resource en kies voor [Properties]
5. In het [SQL Server Properties] scherm klik op de [Dependencies] tab en vervolgens op [Modify]
6. Voeg vanuit de [Available resource] alle beschikbare schijven toe naar [Dependencies] door middel van selecteren van de schijven en op [-->] te klikken. Klik vervolgens op [Ok] en nogmaals op [Ok] om te bevestigen
7. Klik met de rechtermuisknop op de [SQL Server Agent] resource en klik op [Bring online]. De [SQL Server] resource zal nu automatisch ook online gebracht worden omdat de Agent resource afhankelijk is van de Server resource
8. Test de failover functionaliteiten van het cluster


Bijlage A: - SQL Server Setup afbeeldingen


Bijlage B: - SQL Server Service Pack 2 setup afbeeldingen

fn_filestats (This script is useful when you need to identify the source of disk bottlenecks on a database server.)


-- ***************************************************************************
-- Copyright (C) 1991-2003 SQLDEV.NET
--
-- file: fn_filestats.sql
-- descr.: fn_filestats
-- author: Gert E.R. Drapers (GertD@SQLDev.Net)
--
-- @@bof_revsion_marker
-- revision history
-- yyyy/mm/dd by description
-- ========== ======= ========================================================
-- 2005/04.13 gertd v1.0.0.3 rtw
-- 2004/10/14 gertd v1.0.0.2 SEAS version
-- 2003/07/29 gertd v1.0.0.1 fixes
-- 2003/07/06 gertd v1.0.0.0 created
-- @@eof_revsion_marker
-- This function works fine on SQL Server 2000
-- ***************************************************************************

use master
go

exec sp_configure 'allow updates', 1
reconfigure with override
go

if exists (select * from sysobjects where name = 'fn_filestats' and uid = USER_ID('system_function_schema') and xtype = 'TF')
drop function system_function_schema.fn_filestats
go

create function system_function_schema.fn_filestats()
returns @filestats table
(
[DbName] sysname not null,
[DbId] smallint not null,
[FileId] smallint not null,
[NumberReads] bigint not null,
[NumberWrites] bigint not null,
[BytesRead] bigint not null,
[BytesWritten] bigint not null,
[IoStallMS] bigint not null,
[TotalIO] bigint not null,
[TotalBytes] bigint not null,
[AvgStallPerIO] numeric(20, 0) not null,
[AvgBytesPerIO] numeric(20, 0) not null,
[%IO] numeric(20, 3) not null,
[%Bytes] numeric(20, 3) not null,
[%Stall] numeric(20, 3) not null
)
as
begin
declare @TotalIO bigint,
@TotalBytes bigint,
@TotalStall bigint

select @TotalIO = sum(NumberReads + NumberWrites),
@TotalBytes = sum(BytesRead + BytesWritten),
@TotalStall = sum(IoStallMS)
from ::fn_virtualfilestats(-1, -1)

insert into @filestats
select [DbName] = db_name([DbId]),
[DbId],
[FileId],
[NumberReads],
[NumberWrites],
[BytesRead],
[BytesWritten],
[IoStallMS],
[TotalIO] = cast((NumberReads + NumberWrites) as bigint),
[TotalBytes] = (BytesRead + BytesWritten),
[AvgStallPerIO] = ([IoStallMS] / ([NumberReads] + [NumberWrites] + 1)),
[AvgBytesPerIO] = ((BytesRead + BytesWritten) / (NumberReads + NumberWrites + 1)),
[%IO] = (100 * (NumberReads + NumberWrites) / @TotalIO),
[%Bytes] = (100 * (BytesRead + BytesWritten) / @TotalBytes),
[%Stall] = (100 * IoStallMS / @TotalStall)
from ::fn_virtualfilestats(-1, -1)

return
end
go

exec sp_configure 'allow updates', 0
reconfigure with override
go

-- test
select * from ::fn_filestats()
select * from ::fn_filestats() where [%Stall] > 10
go
======================================================

http://blogs.sqlserver.org.au/blogs/greg_linwood/archive/2006/02/25/56.aspx
Measure database file i/o with fn_virtualfilestats (SQL2000 AND SQL2005)
I'm posting another admin script today which can be useed on either SQL Server 2000 or SQL Server 2005 to measure i/o behaviour against specific database files, using the fn_virtualfilestats() system TSQL function.

This script is useful when you need to identify the source of disk bottlenecks on a database server.

For example, you might have identified that a disk bottleneck on your exists on a server via use of a Perfmon counter such as [\\YOURSERVERNAME\LogicalDisk(D:)\Avg. Disk Read Queue Length], but multiple database files exist on the D:\ volume and you're not sure which specific file is causing the i/o activity that is the source of the bottleneck.

The output from this script provides a break-down of specific i/o data on a per-database-file basis, allowing you to see how many bytes have been read to or written from each file (total, since the last restart of SQL Server) and also the total stall time for each file (ms).

More columns were added to the output of fn_virtualfilestats() for SQL Server 2005, providing even further detailed data than from the SQL Server 2000 version of fn_virtualfilestats(). Most significantly, stall time is only provided as a total in the SQL 2000 version but is broken down into read stalls & write stalls in the SQL 2005 version.

When this script runs, it determines which version of SQL Server it is running against & provides the appropriate output for the discovered version. So, when you run this against SQL 2000 you can expect the new SQL 2005 output columns to remain blank.

I've often found fn_virtualfilestats() very useful in demonstrating how much i/o the tempdb can generate compared to user databases. In fact, this is what prompted me to post this script today - I used it yesterday to show a customer that their tempdb was generating 5 x the write i/o activity compared to their main production database. This led to some further useful discussion about file placement.

Anyhow, without further ado, here's the script. Any corrections etc would be welcomed.

Cheers,
Greg

/**********
* fn_virtualfilestats() script
* Greg Linwood
* greg@SolidQualityLearning.com
* Feb 25th, 2006
*
* Collects fn_virtualfilestats() for all databases
* on either SQL 2000 or SQL 2005 instances.
**********/


set nocount on
go
if object_id('tempdb..#filestats') > 0
drop table #filestats
go

declare @ver int
set @ver = cast(serverproperty('Productversion') as char(1))

create table #filestats (
DbId int not null,
DBName varchar (255) not null,
fileid int not null,
FileName varchar (255) not null,
SampleTime datetime not null,
TS bigint null,
NumberReads bigint null,
BytesRead bigint null,
IoStallReadMS bigint null,
NumberWrites bigint null,
BytesWritten bigint null,
IOStallWriteMS bigint null,
IOStallMS bigint null,
BytesOnDisk bigint null,
constraint pk primary key (DbId, fileid, SampleTime))


declare @database_name varchar(255)
declare @database_id int
declare @file_id int
declare @file_name varchar (1000)
declare @sql nvarchar(4000)


declare cr cursor for
select sd.name, sd.dbid, saf.fileid, saf.name
from sysaltfiles saf
join sysdatabases sd on saf.dbid = sd.dbid
order by sd.name, saf.fileid

open cr

fetch next from cr
into @database_name, @database_id, @file_id, @file_name

while @@fetch_status = 0

begin

if @ver = 8
begin

select @sql = N'
insert into #filestats (DBName, FileName, DbId, FileId, SampleTime,
TS, NumberReads, BytesRead, NumberWrites, BytesWritten, IOStallMS)
select @dn, @fn, DbId, FileId, getdate(), [Timestamp], NumberReads,
BytesRead, NumberWrites, BytesWritten, IOStallMS
from :: fn_virtualfilestats(@database_id, @file_id) '
execute sp_executesql @sql
, N'@dn varchar (255), @fn varchar (255), @database_id int, @file_id int'
, @dn = @database_name
, @fn = @file_name
, @database_id = @database_id
, @file_id = @file_id
end

if @ver = 9
begin
select @sql = N'
insert into #filestats (DBName, FileName, DbId, FileId, SampleTime,
TS, NumberReads, BytesRead, IoStallReadMS, NumberWrites, BytesWritten,
IOStallWriteMS, IOStallMS, BytesOnDisk)
select @dn, @fn, DbId, FileId, getdate(), [Timestamp], NumberReads,
BytesRead, IoStallReadMS, NumberWrites, BytesWritten,
IOStallWriteMS, IOStallMS, BytesOnDisk
from :: fn_virtualfilestats(@database_id, @file_id) '
execute sp_executesql @sql
, N'@dn varchar (255), @fn varchar (255), @database_id int, @file_id int'
, @dn = @database_name
, @fn = @file_name
, @database_id = @database_id
, @file_id = @file_id
end

fetch next from cr
into @database_name, @database_id, @file_id, @file_name

end
go
close cr
deallocate cr
go
select * from #filestats
go
if object_id('tempdb..#filestats') > 0
drop table #filestats
go

Published Saturday, 25 February 2006 9:05 AM by Greg_Linwood
Filed Under: SQL Server - Scripts

beheerdb

USE [beheerdb]
GO
/****** Object: StoredProcedure [dbo].[beheerdb_dbc_chk_dbs_all_p] Script Date: 11/17/2008 10:28:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[beheerdb_dbc_chk_dbs_all_p]
AS
SET NOCOUNT ON

DECLARE @dbs_nam AS VARCHAR(50)
DECLARE @opd AS VARCHAR(1024)

DECLARE dbc_dbs_cur CURSOR FOR
SELECT [name]
FROM [master].[dbo].[sysdatabases]
WHERE [dbid] <>2

OPEN dbc_dbs_cur

FETCH NEXT FROM dbc_dbs_cur
INTO @dbs_nam

WHILE @@FETCH_STATUS = 0
BEGIN
SET @opd = 'dbcc checkdb ('+ @dbs_nam + ')'
PRINT 'Database: ' + @dbs_nam
EXEC (@opd)
FETCH NEXT
FROM dbc_dbs_cur
INTO @dbs_nam
END

CLOSE dbc_dbs_cur

DEALLOCATE dbc_dbs_cur

=====================================
Schedule a job to begin daily at 2:00
=====================================
USE [beheerdb]
GO
/****** Object: StoredProcedure [dbo].[beheerdb_dbc_her_ind_dbs_all_p] Script Date: 11/17/2008 10:13:41 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[beheerdb_dbc_her_ind_dbs_all_p]
AS
DECLARE @SQL Varchar(8000)
SET @SQL = ''
SELECT @SQL = @SQL + 'EXEC ' + [name] +
'..sp_MSforeachtable @command1=''DBCC DBREINDEX (''''?'''')''' + Char(13)
FROM [master].[dbo].[sysdatabases]
WHERE [dbid] > 4
PRINT @SQL
EXEC (@SQL)
=====================================
Schedule a job to begin daily at 2:30
=====================================

USE [beheerdb]
GO
/****** Object: StoredProcedure [dbo].[beheerdb_dbc_upd_sts_dbs_all_p] Script Date: 11/17/2008 10:15:03 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[beheerdb_dbc_upd_sts_dbs_all_p]
AS
SET NOCOUNT ON

DECLARE @dbs_nam AS varchar(64)
DECLARE @opd AS varchar(1024)
DECLARE dbc_dbs_cur CURSOR FOR
SELECT [name]
FROM [master].[dbo].[sysdatabases]
WHERE [dbid] > 4

OPEN dbc_dbs_cur

FETCH NEXT
FROM dbc_dbs_cur
INTO @dbs_nam

WHILE @@FETCH_STATUS = 0
BEGIN
SET @opd = 'Use ' + @dbs_nam + '
exec sp_updatestats'
EXEC (@opd)
FETCH NEXT
FROM dbc_dbs_cur
INTO @dbs_nam
END

CLOSE dbc_dbs_cur

DEALLOCATE dbc_dbs_cur

======================================
Schedule a job to begin daily at 5:45
======================================

USE [beheerdb]
GO
/****** Object: StoredProcedure [dbo].[beheerdb_dbc_upd_usg_dbs_all_p] Script Date: 11/17/2008 10:27:25 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[beheerdb_dbc_upd_usg_dbs_all_p]
AS
SET NOCOUNT ON

DECLARE @dbs_nam AS VARCHAR(50)
DECLARE @opd AS VARCHAR(1024)
DECLARE dbc_dbs_cur CURSOR FOR
SELECT [name]
FROM [master].[dbo].[sysdatabases]
WHERE [dbid] > 4

OPEN dbc_dbs_cur

FETCH NEXT
FROM dbc_dbs_cur
INTO @dbs_nam

WHILE @@FETCH_STATUS = 0
BEGIN
SET @opd = 'dbcc updateusage ('+ @dbs_nam + ')'
EXEC (@opd)
FETCH NEXT
FROM dbc_dbs_cur
INTO @dbs_nam
END

CLOSE dbc_dbs_cur

DEALLOCATE dbc_dbs_cur
======================================
Schedule a job to begin daily at 5:30
======================================

backing up user databases in SQL Server 2005

-- backing up user databases in SQL Server

declare @DatabaseName varchar(300)
,@BackupSQL varchar(8000)
,@Timestamp varchar(30)
,@DirectoryPath varchar(2000)
,@FullPath varchar(2500)
,@RecoveryModel int

set @DirectoryPath = 'D:\MSSQL\BACKUP\'

-- create a timestamp for the backup file name
set @TimeStamp = convert(varchar, getdate(),112) + replace(convert(varchar, getdate(),108),':','')

-- get user databases only
declare Database_Cursor cursor for
select d.name
from sys.databases d
where d.name not in('master','tempdb','model','msdb')

open Database_Cursor

fetch next from Database_Cursor
into @DatabaseName

while @@fetch_status = 0
begin

set @FullPath = ''
set @FullPath = @DirectoryPath + @DatabaseName

exec sys.xp_create_subdir @FullPath

set @BackupSQL = ''
set @BackupSQL = @BackupSQL + 'BACKUP DATABASE ' + @DatabaseName + ' TO DISK = N''' + @FullPath + '\' + @DatabaseName + '_' + @TimeStamp + '.bak'' WITH NOFORMAT, NOINIT, SKIP'

exec (@BackupSQL)

-- backups tlogs
select @RecoveryModel = d.recovery_model from sys.databases as d where d.name = @DatabaseName
-- only backup transaction logs for databases set for Full Recovery
if @RecoveryModel = 1
begin
set @BackupSQL = ''
set @BackupSQL = @BackupSQL + 'BACKUP LOG ' + @DatabaseName + ' TO DISK = N''' + @FullPath + '\' + @DatabaseName + '_' + @TimeStamp + '.trn'' WITH NOFORMAT, NOINIT, SKIP'
exec(@BackupSQL)
end

fetch next from Database_Cursor
into @DatabaseName

end

close Database_Cursor
deallocate Database_Cursor

Dynamically Creating Triggers for Cascade Actions

--------------------------------------------------------------------
-- Appendix F - Dynamically Creating Triggers for Cascade Actions --
--------------------------------------------------------------------

-- Listing F-1: Creation Script for the sp_RICascadeDelete Stored Procedure
CREATE PROC sp_RICascadeDelete
@prmtbl sysname, -- Primary (referenced) table
@sectbl sysname, -- Secondary (referencing) table
@prmcol sysname, -- Primary (referenced) column
@seccol sysname -- Secondary (referencing) column
AS

DECLARE @ENTER AS char(1)
DECLARE @cmd AS varchar(8000)

SET @ENTER = CHAR(10)

IF @prmtbl != @sectbl
BEGIN
SET @cmd =
'CREATE TRIGGER trg_d_' + @prmtbl + '_on_delete_cascade ON ' +
@prmtbl + ' FOR DELETE' + @ENTER +
'AS' + @ENTER +
@ENTER +
'IF @@rowcount = 0' + @ENTER +
' RETURN' + @ENTER +
@ENTER +
'DELETE FROM ' + @sectbl + @ENTER +
'FROM ' + @ENTER +
' ' + @sectbl + ' AS S' + @ENTER +
' JOIN' + @ENTER +
' deleted AS D ON S.' + @seccol + ' = D.' + @prmcol + @ENTER
END
ELSE
BEGIN
SET @cmd =
'CREATE TRIGGER trg_d_' + @prmtbl + '_on_delete_cascade ON ' +
@prmtbl + ' FOR DELETE' + @ENTER +
'AS' + @ENTER +
@ENTER +
'IF EXISTS(SELECT *' + @ENTER +
' FROM ' + @ENTER +
' ' + @prmtbl + ' AS S' + @ENTER +
' JOIN' + @ENTER +
' deleted AS D ON S.' + @seccol + ' = D.' + @prmcol +')' + @ENTER +
' DELETE FROM ' + @sectbl + @ENTER +
' FROM' + @ENTER +
' ' + @sectbl + ' AS S' + @ENTER +
' JOIN' + @ENTER +
' deleted AS D ON S.' + @seccol + ' = D.' + @prmcol + @ENTER

PRINT 'Recursive triggers should be turned on.' + @ENTER +
'Use EXEC sp_dboption ' + DB_NAME() +
', ''recursive triggers'', ''true'''+ @ENTER
END

EXECUTE(@cmd)
GO

-- Listing F-2: Creation Script for the sp_RIPreventDelete Stored Procedure
CREATE PROC sp_RIPreventDelete
@prmtbl sysname, -- Primary (referenced) table
@sectbl sysname, -- Secondary (referencing) table
@prmcol sysname, -- Primary (referenced) column
@seccol sysname -- Secondary (referencing) column
AS

DECLARE @ENTER AS char(1)
DECLARE @cmd AS varchar(8000)

SET @ENTER = CHAR(10)

SET @cmd =
'CREATE TRIGGER trg_d_' + @prmtbl + '_prevent_delete ON ' +
@prmtbl + ' FOR DELETE' + @ENTER +
'AS' + @ENTER +
@ENTER +
'IF @@rowcount = 0' + @ENTER +
' RETURN' + @ENTER +
@ENTER +
'IF EXISTS(SELECT *' + @ENTER +
' FROM ' + @ENTER +
' ' + @sectbl + ' AS S' + @ENTER +
' JOIN' + @ENTER +
' deleted AS D ON S.' + @seccol + ' = D.' + @prmcol + ')' + @ENTER +
'BEGIN' + @ENTER +
' RAISERROR(''You are trying to delete rows from ' + @prmtbl +
' that have related rows in ' + @sectbl +
'.TRANSACTION rolled back.'', 10, 1)' + @ENTER +
' ROLLBACK TRANSACTION' + @ENTER +
'END'

EXECUTE(@cmd)
GO

-- Listing F-3: Creation Script for the sp_RICascadeUpdate Stored Procedure
CREATE PROC sp_RICascadeUpdate
@prmtbl sysname, -- Primary (referenced) table
@sectbl sysname, -- Secondary (referencing) table
@prmcol sysname, -- Primary (referenced) column
@seccol sysname -- Secondary (referencing) column
AS

DECLARE @ENTER AS char(1)
DECLARE @cmd AS varchar(8000)

SET @ENTER = CHAR(10)

SET @cmd =
'CREATE TRIGGER trg_u_' + @prmtbl + '_on_update_cascade ON ' +
@prmtbl + ' FOR UPDATE' + @ENTER +
'AS' + @ENTER +
@ENTER +
'DECLARE @numrows AS int' + @ENTER +
'SET @numrows = @@rowcount' + @ENTER +
'IF UPDATE(' + @prmcol + ')' + @ENTER +
' IF @numrows = 1' + @ENTER +
' UPDATE ' + @sectbl + @ENTER +
' SET ' + @seccol + ' = (SELECT ' + @prmcol + ' FROM inserted)' + @ENTER +
' FROM ' + @ENTER +
' ' + @sectbl + ' AS S' + @ENTER +
' JOIN' + @ENTER +
' deleted AS D ON S.' + @seccol + ' = D.' + @prmcol + @ENTER +
' ELSE IF @numrows > 1' + @ENTER +
' BEGIN' + @ENTER +
' RAISERROR(''Updates to more than one row in ' + @prmtbl +
' are not allowed. TRANSACTION rolled back.'', 10, 1)' + @ENTER +
' ROLLBACK TRANSACTION' + @ENTER +
' END' + @ENTER

EXEC(@cmd)

PRINT 'Only single row updates are allowed to ' + @prmtbl + '.' + @ENTER +
'To support multi-row updates add a surrogate key and alter the trigger:' + @ENTER

PRINT 'ALTER TABLE ' + @prmtbl + @ENTER +
' ADD surrogate_key int NOT NULL IDENTITY(1,1)' + @ENTER +
' CONSTRAINT UNQ_' + @prmtbl + '_surrogate_key UNIQUE' + @ENTER +
'GO' + @ENTER

PRINT 'ALTER TRIGGER trg_u_' + @prmtbl + '_on_update_cascade ON ' +
@prmtbl + ' FOR UPDATE' + @ENTER +
'AS' + @ENTER +
@ENTER +
'DECLARE @numrows AS int' + @ENTER +
'SET @numrows = @@rowcount' + @ENTER +
'IF UPDATE(surrogate_key)' + @ENTER +
'BEGIN' + @ENTER +
' RAISERROR(''Updates to surrogate_key are not allowed. TRANSACTION rolled back.'', 10, 1)' + @ENTER +
' ROLLBACK TRANSACTION' + @ENTER +
'END' + @ENTER +
'ELSE' + @ENTER +
' IF UPDATE(' + @prmcol + ') AND @numrows > 0' + @ENTER +
' UPDATE ' + @sectbl + @ENTER +
' SET ' + @seccol + ' = I.' + @prmcol + @ENTER +
' FROM ' + @ENTER +
' ' + @sectbl + ' AS S' + @ENTER +
' JOIN' + @ENTER +
' deleted AS D ON S.' + @seccol + ' = D.' + @prmcol + @ENTER +
' JOIN' + @ENTER +
' inserted AS I ON D.surrogate_key = I.surrogate_key' + @ENTER +
'GO' + @ENTER
GO

CREATE PROC sp_RIPreventUpdate
@prmtbl sysname, -- Primary (referenced) table
@sectbl sysname, -- Secondary (referencing) table
@prmcol sysname, -- Primary (referenced) column
@seccol sysname -- Secondary (referencing) column
AS

DECLARE @ENTER AS char(1)
DECLARE @cmd AS varchar(8000)

SET @ENTER = CHAR(10)

SET @cmd =
'CREATE TRIGGER trg_d_' + @prmtbl + '_prevent_update ON ' +
@prmtbl + ' FOR UPDATE' + @ENTER +
'AS' + @ENTER +
@ENTER +
'IF @@rowcount = 0' + @ENTER +
' RETURN' + @ENTER +
@ENTER +
'IF EXISTS(SELECT *' + @ENTER +
' FROM' + @ENTER +
' ' + @sectbl + ' AS S' + @ENTER +
' JOIN' + @ENTER +
' deleted AS D ON S.' + @seccol + ' = D.' + @prmcol + ')' + @ENTER +
'BEGIN' + @ENTER +
' RAISERROR(''You are trying to update rows in ' + @prmtbl +
' that have related rows in ' + @sectbl +
'.TRANSACTION rolled back.'', 10, 1)' + @ENTER +
' ROLLBACK TRANSACTION' + @ENTER +
'END'

EXECUTE(@cmd)
GO

-- Listing F-5: Creation Script for the sp_RIPreventInsUpd Stored Procedure
CREATE PROC sp_RIPreventInsUpd
@prmtbl sysname, -- Primary (referenced) table
@sectbl sysname, -- Secondary (referencing) table
@prmcol sysname, -- Primary (referenced) column
@seccol sysname -- Secondary (referencing) column
AS

DECLARE @ENTER AS char(1)
DECLARE @cmd AS varchar(8000)

SET @ENTER = CHAR(10)

IF @prmtbl != @sectbl
BEGIN
SET @cmd =
'CREATE TRIGGER trg_iu_' + @sectbl + '_prevent_insupd ON ' +
@sectbl + ' FOR INSERT, UPDATE' + @ENTER +
'AS' + @ENTER +
@ENTER +
'DECLARE @numrows int' + @ENTER +
'SET @numrows = @@rowcount' + @ENTER +
@ENTER +
'IF UPDATE(' + @seccol + ') AND @numrows > 0' + @ENTER +
' IF @numrows <> (SELECT' + @ENTER +
' COUNT(*)' + @ENTER +
' FROM' + @ENTER +
' ' + @prmtbl + ' AS P' + @ENTER +
' JOIN' + @ENTER +
' inserted AS I ON P.' + @prmcol + ' = I.' + @seccol + ')' + @ENTER +
' BEGIN' + @ENTER +
' RAISERROR(''Result rows in ' + @sectbl + ' are orphaned. TRANSACTION rolled back.'', 10, 1)' + @ENTER +
' ROLLBACK TRANSACTION' + @ENTER +
' END' + @ENTER
END
ELSE
BEGIN
SET @cmd =
'CREATE TRIGGER trg_iu_' + @sectbl + '_prevent_insupd ON ' +
@sectbl + ' FOR INSERT, UPDATE' + @ENTER +
'AS' + @ENTER +
@ENTER +
'IF @@rowcount > 0 AND UPDATE(' + @seccol + ')' + @ENTER +
'BEGIN' + @ENTER +
' DECLARE @numrows int' + @ENTER +
@ENTER +
' SELECT' + @ENTER +
' @numrows = COUNT(*)' + @ENTER +
' FROM' + @ENTER +
' inserted' + @ENTER +
' WHERE' + @ENTER +
' ' + @seccol + ' IS NOT NULL' + @ENTER +
@ENTER +
' IF @numrows <> (SELECT' + @ENTER +
' COUNT(*)' + @ENTER +
' FROM' + @ENTER +
' ' + @prmtbl + ' AS P' + @ENTER +
' JOIN' + @ENTER +
' inserted AS I ON P.' + @prmcol + ' = I.' + @seccol + ')' + @ENTER +
' BEGIN' + @ENTER +
' RAISERROR(''Result rows in ' + @sectbl + ' are orphaned. TRANSACTION rolled back.'', 10, 1)' + @ENTER +
' ROLLBACK TRANSACTION' + @ENTER +
' END' + @ENTER +
'END' + @ENTER
END

EXECUTE(@cmd)
GO

-- Listing F-6: Creation Script for the sp_CreateRelationship Stored Procedure
CREATE PROC sp_CreateRelationship
@prmtbl sysname, -- Primary (referenced) table
@sectbl sysname, -- Secondary (referencing) table
@prmcol sysname, -- Primary (referenced) column
@seccol sysname, -- Secondary (referencing) column,
@deletecascade bit = 1, -- determines whether to support cascade delete
@updatecascade bit = 1 -- determines whether to support cascade update
AS

DECLARE @ENTER AS char(1)
DECLARE @cmd AS varchar(8000)

SET @ENTER = CHAR(10)

IF @deletecascade = 1
BEGIN
PRINT 'Creating delete cascade trigger on ' + @prmtbl + '...' + @ENTER
EXEC sp_RICascadeDelete
@prmtbl = @prmtbl,
@sectbl = @sectbl,
@prmcol = @prmcol,
@seccol = @seccol
END
ELSE
BEGIN
PRINT 'Creating prevent delete trigger on ' + @prmtbl + '...' + @ENTER
EXEC sp_RIPreventDelete
@prmtbl = @prmtbl,
@sectbl = @sectbl,
@prmcol = @prmcol,
@seccol = @seccol
END

IF @updatecascade = 1
BEGIN
PRINT 'Creating update cascade trigger on ' + @prmtbl + '...' + @ENTER
EXEC sp_RICascadeUpdate
@prmtbl = @prmtbl,
@sectbl = @sectbl,
@prmcol = @prmcol,
@seccol = @seccol
END
ELSE
BEGIN
PRINT 'Creating prevent update trigger on ' + @prmtbl + '...' + @ENTER
EXEC sp_RIPreventUpdate
@prmtbl = @prmtbl,
@sectbl = @sectbl,
@prmcol = @prmcol,
@seccol = @seccol
END

PRINT 'Creating prevent insert / update trigger on ' + @sectbl + '...' + @ENTER
EXEC sp_RIPreventInsUpd
@prmtbl = @prmtbl,
@sectbl = @sectbl,
@prmcol = @prmcol,
@seccol = @seccol
GO

-- Listing F-7: Using the sp_CreateRelationship Stored Procedure to Create Cascading Triggers in a Two-Tables Relationship Scenario
EXEC sp_CreateRelationship
@prmtbl = Orders,
@sectbl = OrderDetails,
@prmcol = orderid,
@seccol = orderid,
@deletecascade = 1,
@updatecascade = 1

-- Listing F-8: Output From the sp_CreateRelationship Stored Procedure in a Two-Tables Relationship Scenario
Creating delete cascade trigger on Orders...

Creating update cascade trigger on Orders...

Only single row updates are allowed to Orders.
To support multi-row updates add a surrogate key and alter the trigger:

ALTER TABLE Orders
ADD surrogate_key int NOT NULL IDENTITY(1,1)
CONSTRAINT UNQ_Orders_surrogate_key UNIQUE
GO

ALTER TRIGGER trg_u_Orders_on_update_cascade ON Orders FOR UPDATE
AS

DECLARE @numrows AS int
SET @numrows = @@rowcount
IF UPDATE(surrogate_key)
BEGIN
RAISERROR('Updates to surrogate_key are not allowed. TRANSACTION rolled back.', 10, 1)
ROLLBACK TRANSACTION
END
ELSE
IF UPDATE(orderid) AND @numrows > 0
UPDATE OrderDetails
SET orderid = I.orderid
FROM
OrderDetails AS S
JOIN
deleted AS D ON S.orderid = D.orderid
JOIN
inserted AS I ON D.surrogate_key = I.surrogate_key
GO

Creating prevent insert / update trigger on OrderDetails...

-- Listing F-9: Using the sp_CreateRelationship Stored Procedure to Create Cascading Triggers in a Single-Tables Relationship Scenario
EXEC sp_CreateRelationship
@prmtbl = Employees,
@sectbl = Employees,
@prmcol = empid,
@seccol = mgrid,
@deletecascade = 1,
@updatecascade = 1

-- Listing F-10: Output From the sp_CreateRelationship Stored Procedure in a Single-Tables Relationship Scenario
Creating delete cascade trigger on Employees...

Recursive triggers should be turned on.
Use EXEC sp_dboption testdb, 'recursive triggers', 'true'

Creating update cascade trigger on Employees...

Only single row updates are allowed to Employees.
To support multi-row updates add a surrogate key and alter the trigger:

ALTER TABLE Employees
ADD surrogate_key int NOT NULL IDENTITY(1,1)
CONSTRAINT UNQ_Employees_surrogate_key UNIQUE
GO

ALTER TRIGGER trg_u_Employees_on_update_cascade ON Employees FOR UPDATE
AS

DECLARE @numrows AS int
SET @numrows = @@rowcount
IF UPDATE(surrogate_key)
BEGIN
RAISERROR('Updates to surrogate_key are not allowed. TRANSACTION rolled back.', 10, 1)
ROLLBACK TRANSACTION
END
ELSE
IF UPDATE(empid) AND @numrows > 0
UPDATE Employees
SET mgrid = I.empid
FROM
Employees AS S
JOIN
deleted AS D ON S.mgrid = D.empid
JOIN
inserted AS I ON D.surrogate_key = I.surrogate_key
GO

Creating prevent insert / update trigger on Employees...