<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Edwin M Sarmiento&gt;I wish this was available years back &#8211; SQL Server 2005 Always On Technologies Part 1 &#8211; Edwin M Sarmiento</title>
	<atom:link href="https://www.edwinmsarmiento.com/i-wish-this-was-available-years-back-sql-server-2005-always-on-technologies-part-1/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.edwinmsarmiento.com</link>
	<description>Intentional Excellence</description>
	<lastBuildDate>Mon, 13 Apr 2026 21:00:49 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
<site xmlns="com-wordpress:feed-additions:1">84283043</site>		<item>
		<title>&gt;I wish this was available years back &#8211; SQL Server 2005 Always On Technologies Part 1</title>
		<link>https://www.edwinmsarmiento.com/i-wish-this-was-available-years-back-sql-server-2005-always-on-technologies-part-1/</link>
		<comments>https://www.edwinmsarmiento.com/i-wish-this-was-available-years-back-sql-server-2005-always-on-technologies-part-1/#respond</comments>
		<pubDate>Fri, 28 Sep 2007 00:20:00 +0000</pubDate>
		<dc:creator>Edwin M Sarmiento</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://bassplayerdoc.wordpress.com/2007/09/28/i-wish-this-was-available-years-back-sql-server-2005-always-on-technologies-part-1</guid>

				<description><![CDATA[&#62;In response to requests made after I did a presentation on TechEd Asia 2007 on SQL Server 2005 Always On Technologies, I&#8217;ve made the content available on my blog. In as much as we want to, there are not as many options in SQL Server 2000 to address disaster recovery caused by human errors. And [&#8230;]]]></description>
					<content:encoded><![CDATA[<p>&gt;<span style="font-family:arial;">In response to requests made after I did a presentation on TechEd Asia 2007 on SQL Server 2005 Always On Technologies, I&#8217;ve made the content available on my blog. </span></p>
<p><span style="font-family:arial;">In as much as we want to, there are not as many options in SQL Server 2000 to address disaster recovery caused by human errors. And when we think about disaster recovery and high availability, we are often tempted to think about hardware solutions. With SQL Server 2005, we have a lot of options. This will be a series of blog entries discussion about the high availability options in SQL Server 2005. I would like to highlight, though, that disaster recovery is more a process than technology. We may have the available technologies at our disposal but if we do not have the right process, then, its practically useless. Prevention is one option. Let&#8217;s take a look at a simple scenario. Imagine a developer accidentally connecting to a production database and dropped a table. Now, if this table has implemented referential integrity and has foreign key relationships established on related tables, the related tables would definitely prohibit the execution of the <strong><span style="font-size:85%;">DROP TABLE</span></strong> command due to referential integrity. But what about this table? Let&#8217;s say the <strong><span style="font-size:85%;">Employees</span></strong> table is related to the <strong><span style="font-size:85%;">Department</span></strong> table and a referential integrity is defined between them. We won&#8217;t be able to drop the <strong><span style="font-size:85%;">Employees</span></strong> table because it references the <strong><span style="font-size:85%;">Department</span></strong> table. But nobody is stopping us from dropping the <strong><span style="font-size:85%;">Department</span></strong> table. The best way to prevent this scenario in SQL Server 2005 is to implement DDL(data definition language) triggers. We are all familiar with DML triggers in previous versions of SQL Server. DDL triggers are used to audit and/or prevent DDL statements at the server-level or at the database-level. You can prevent accidental data deletion (i.e., trapping and rolling back an attempt to drop a table) and unexpected schema changes. A benefit of using a DDL trigger is that it forms a part of an implicit transaction which caused the trigger to fire and, when necessary, rollback the statement when necessary. The data related to the event can be trapped even if the statement that caused the trigger to fire has been rolled back. This is beneficial if we want to audit who did what on either database or server level. A complete description of SQL Server 2005 DDL triggers can be found on the <a href="http://msdn2.microsoft.com/en-us/library/ms191438.aspx">MSDN site</a>. </span></p>
<p><span style="font-family:arial;">Let me walkthrough a simple example on using a DDL trigger. Using the very familiar Northwind database (the Northwind database does not come with the default installation of SQL Server 2005. You can download the source from the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=06616212-0356-46a0-8da2-eebc53a68034&amp;DisplayLang=en">Microsoft Download Center</a>). First, create a table which will contain the metadata of the DDL query. We will use this to store those information for audit purposes </span></p>
<p><span style="font-size:85%;"><span style="color:#000099;">USE Northwind;<br />go</span></span><span style="font-size:85%;"><span style="color:#000099;"><br />CREATE TABLE AuditDDLOperations<br />( OpID int NOT NULL identity CONSTRAINT AuditDDLOperationsPK PRIMARY KEY CLUSTERED,<br />LoginName sysname NOT NULL,<br />UserName sysname NOT NULL,<br />PostTime datetime NOT NULL,<br />EventType nvarchar(100) NOT NULL,<br />DDLOp nvarchar(2000) NOT NULL);<br />GO</span><br /></span><span style="font-size:0;"><br /><span style="font-family:arial;"><span style="font-family:arial;font-size:100%;">Then, we will create a database-level DDL trigger.</span> </span></span></p>
<p><span style="font-size:85%;color:#000099;">CREATE TRIGGER PreventAllDDL<br />ON DATABASE<br />WITH ENCRYPTION<br />FOR DDL_DATABASE_LEVEL_EVENTS<br />AS DECLARE @data XMLSET<br />@data = EVENTDATA()<br />RAISERROR (&#8216;DDL Operations are prohibited on this production database. Please contact IT Division for proper change control procedures.&#8217;, 16, -1)<br />ROLLBACK<br />INSERT AuditDDLOperations (LoginName, UserName, PostTime, EventType, DDLOp)</span><br /><span style="font-size:85%;color:#000099;">VALUES (SYSTEM_USER, CURRENT_USER, GETDATE(), @data.value(&#8216;(/EVENT_INSTANCE/EventType)[1]&#8217;, &#8216;nvarchar(100)&#8217;), @data.value(&#8216;(/EVENT_INSTANCE/TSQLCommand)[1]&#8217;, &#8216;nvarchar(2000)&#8217;) )<br />RETURN;<br />GO</span><span style="font-size:0;"><span style="color:#000099;"><br /></span></span></p>
<p><span style="font-size:0;"><span style="font-family:arial;font-size:100%;">The <strong><span style="font-size:85%;">CREATE TRIGGER</span></strong> statement consists of (1) the scope, which in this case is a database-level scope, (2) WITH ENCRYPTION option to simply hide the trigger definition, (3) the event on which the trigger will be associated with, this case will be all DDL events at the database level, (4) the EVENTDATA() function which returns information about server or database events and is called when an event notification fires, and (5) an INSERT statement to store the details of the EVENTDATA() function inside the table we created in the previous script. Now, to test the trigger, simple run any DDL statement on the Northwind database</span></span></p>
<p><span style="font-size:85%;"><span style="color:#000099;">CREATE TABLE Foo(col1 int);<br />go<br />DROP TABLE AuditDDLOperations;<br />GO</span></span></p>
<p><span style="color:#000099;"></span><span style="font-family:arial;">The previous statements are very simple DDL statements &#8211; one to create a table and one to drop a table.  These statements will raise an error defined in the DDL trigger.  To investigate the DDL statements and who executed them, we run a <strong><span style="font-size:85%;">SELECT</span></strong> query against the table we created</span></p>
<p><span style="font-size:85%;"><span style="color:#000099;">SELECT * FROM AuditDDLOperations;<br /></span><span style="color:#000099;">GO</span></span><span style="font-size:0;"></p>
<p></span><span style="font-family:arial;">The key thing here is implementing DDL triggers as part of your database implementation strategy to minimize disaster caused by human errors.  In the next part of this series, I&#8217;ll talk about how you can recover from a dropped database in cases where you don&#8217;t have a DDL trigger defined in your database</span></p>
<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/92377218009570869-3177380399452132339?l=bassplayerdoc.blogspot.com' alt='' /></div>
]]></content:encoded>
			

		<wfw:commentRss>https://www.edwinmsarmiento.com/i-wish-this-was-available-years-back-sql-server-2005-always-on-technologies-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
				<post-id xmlns="com-wordpress:feed-additions:1">10</post-id>	</item>
	</channel>
</rss>