tag:blogger.com,1999:blog-72733862023-11-15T13:01:17.311-06:00SQL MusingsORDER BY RAND()Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.comBlogger21125tag:blogger.com,1999:blog-7273386.post-73958031969018197982011-11-08T08:43:00.000-06:002011-11-08T08:43:09.098-06:00The command line is dead... long live the command line!So, MS wants us to believe that Powershell is what separates effective admins from non-effective ones. I'm on board. I'll take a CLI over a GUI most days. But seriously, give us a good place to run it. The Windows console sucks. Why can't I change the width of the window by dragging the side? I'm not even asking for dynamic word wrapping here, just the ability to widen the damn window. Why can't I select lines of text? Or double-click on a word and have the word highlight? Or extend my selection? Perhaps I'm being spoiled by my Unix roots where xterm and friends have been doing this for years (and by that, I mean decades). If you want me to take you seriously MS, make your CLI environment not suck.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-51560943028050303192011-09-28T10:56:00.000-05:002011-10-17T14:09:45.790-05:00Modulo difficulties, life is easyThe other day, I had a request from a BA. The gist of it was that we had a column in the database defined as a decimal(5,4) and yet the data as defined by the regulatory body only provided three places after the decimal point. He wanted to know if any data had somehow crept into the database that was utilizing the (seemingly superfluous) fourth place. On its face, this seems like a difficult problem. Admittedly, when I first heard it, I couldn't come up with something off the top of my head. But then I remembered that I have a plaque on my wall that says "B.S. Math", so I decided to leverage that. Enter the modulo operator.<br />
<br />
Before we can talk about the <a href="http://msdn.microsoft.com/en-us/library/ms190279.aspx">modulo operator</a>, we're going to have to flash back to when you learned long division. I know that it was traumatic for you, but trust me, this will bear fruit. If you recall, when you divide one number by another and that division doesn't result in "even division" (that is when the divisor goes into the dividend an integer number of times), you have the option of either expanding it into a decimal or just saying "screw it... here's what's left". By way of a worked example, if I divide 5 by 2, I can either say that it's 2.5, or 2 with a remainder of 1. In simplest terms, the modulo operator takes as arguments a divisor and a dividend and returns the remainder.<br />
<br />
So how does that apply to the stated problem? That is, if I have an arbitrary number that's of the form 0.1234, how do I tell if there is a digit in the ten thousandths place? Here's what I did. If I multiply all such numbers by 10,000 and then evaluate that number modulo (mod for short) 10, that will return the ones place to me. If the result of that operation is not 0, then I have a non-zero digit in the ten thousandths place. For you code junkies out there:<br />
<br />
<pre><code>
select value
from table
where convert(int, 10000*value) % 10 > 0
</code></pre><br />
The mod operator is useful in a lot of other situations. For instance, let's say that you need to break up a group into n smaller groups. Mod is your friend here. The following code will add a column to the result set called "g" that gives you the group number. In the example, I chose 2 as my modulus, so "g" will take values 0 and 1.<br />
<br />
<pre><code>
select row_number() over (order by Id) as [g] % 2, *
from table
</code></pre><br />
Have you ever needed to make a report where alternating rows had different formatting (and your reporting tool of choice doesn't support this natively)? The above code makes this almost trivial.<br />
<br />
So there you have it. The mod function can be a useful tool in your toolbox. Have fun!<br />
<br />Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-25268651638830633932011-08-26T15:56:00.000-05:002011-08-26T15:56:40.899-05:00On why accurate testing conditions are vitalSo, I was just reading an article detailing the account of how Osama bin Laden was killed. You can read it for yourself <a href="http://www.newyorker.com/reporting/2011/08/08/110808fa_fact_schmidle?currentPage=all">here</a>. What struck me in reading it was when they explained why the helicopter crashed into the courtyard on initial entry. To make a long story short, when they set up a simulation for the Navy SEALs to practice on, the fence was chain link. The actual compound had solid walls. The problem is that the former allows the rotor wash to dissipate. The latter doesn't, and it causes interference with the helicopter. So, the testing conditions and the actual conditions were not the same. As a result, the live run didn't go like the tests had. Fortunately, the pilot was quick on his feet and was able to salvage the mission.<br />
<br />
We as IT professionals can learn from this. When you test something, try your best to make the testing environment as much like the production environment as possible. OS patch level, size, quality of data, etc can all affect performance in one way or another. You can try to predict how, but often times it's just easier to simulate your situation as accurately as possible. Because if you don't, you may find yourself crashing into a wall. Will you be able to recover?Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-10502369947321251072011-08-12T19:00:00.001-05:002011-08-12T19:00:06.863-05:00Converting between SID and account nameIn a previous post, I mentioned the need to convert between Windows SID and the account name. A little Google-ing helped me create the following little powershell script arose<br />
<br />
<code><pre>param(
[string] $sid
)
$objSID = New-Object System.Security.Principal.SecurityIdentifier ( $sid )
$User = $objSID.Translate( [System.Security.Principal.NTAccount] )
$User.Value
</pre></code><br />
<br />
Save that in a file (I called mine "account_from_sid.ps1"). Now, you can say "account_from_sid <sid here>" and get an account name back. Handy!<br />
Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-54219256292726418132011-08-12T18:53:00.004-05:002011-08-12T18:53:00.738-05:00I ♥ WinDirStatSo, part of my duties as an administrator entail being a janitor. Specifically, cleaning up files when a disk fills up. In the interest of working smarter and not harder, I like to use <a href="http://portableapps.com/apps/utilities/windirstat_portable">WinDirStat</a> to find me the heavy hitters quickly. I especially like that it shows me what's in people's recycle bin (which, can we disable that universally on servers please?). The problem is that it gives the recycle bin's owner by <acronym title="Windows Security Identifier">SID</acronym>. That's less than helpful when you need to find someone to <strike>put the hurt on</strike> have a conversation with. In a future post, I'll show you the powershell script that I came up with to do the conversion.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com1tag:blogger.com,1999:blog-7273386.post-27767335697812327412011-05-13T16:45:00.000-05:002011-05-13T16:45:21.962-05:00MS 70-432 passedSo... I have grand aspirations. With the reworking of the MCM program, I decided it was time to get some certifications under my belt (since they go towards something more grand now). Today, I took my first MS test and have to say that the experience wasn't horrible. I have a long way to go to the MCM, but you have to start somewhere.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-40842317791656772372011-05-09T06:52:00.000-05:002011-05-09T06:52:48.273-05:00Blaze your own trailNot to brag, but I've been reading <a href="http://xkcd.com">xkcd</a> since before it was cool. The one from <a href="http://xkcd.com/896/">today</a> struck a chord with me. Specifically, the second-to-last panel. It's been said many times, many ways before. I can think of a couple of other phrasings of it off of the top of my head: "Seek not to follow in the footsteps of the masters. Seek what they sought." and even "You cannot become that which you admire." The point of all of this is that I see so many people trying to succeed (by whatever metric success is measured by) by trying to mimic the actions of those that are considered successful. A lot of success, in my opinion, is circumstance. Being in the right place at the right time. Knowing the right people. So rather than try to duplicate success, try to figure out <em>what</em> those you consider successful were trying to accomplish rather than <em>how</em> they did it. You have talents that they don't. Use them to blaze your own trail.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-75237558624748591092011-04-26T20:28:00.000-05:002011-04-26T20:28:09.100-05:00The software industry and NASANo... I'm not talking about how NASA uses or develops software. We typically call software releases "launches" and got to thinking about parallels that can be drawn between software launches and space shuttle launches.<br />
<br />
<a name='more'></a><br />
<br />
In both cases, the event is what the management types like to call "mission critical". When they launch a space shuttle, they set a launch day. However, nobody faults NASA for calling off a launch <i>for any reason</i>. After all, we're talking about a lot of money and, more importantly, people's lives at stake. Maybe I've been unlucky, but it's been my experience that the same cannot be said of software launches. I'll grant that it's typically not the same scale. But there seems to be a willingness to "launch" software with known defects in the interest of getting it out the door. And while I can appreciate that at some level, I think the software industry would benefit if we treated software launches more like shuttle launches. Treat it as though you're strapping a couple of people to a multi-ton hunk of metal and electronics filled with liquid oxygen and throwing it out of the atmosphere. That is to say a risky endeavor where you won't be able to fix things <i>in situ</i>. Listen when the QA guy says "Houston, we have a problem". Your mission specialists will thank you for it.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-87504192416924717332011-04-22T12:53:00.000-05:002011-04-22T12:53:05.014-05:00The blog's been a bit fallow...Hi all,<br />
<br />
It's been a while since I rapped at you. See, the company that I work for has a love/hate relationship with web filtering. Or, perhaps more specifically, they're updating the filters employed with what I can only describe as enthusiastic capriciousness. For a long time, this site was blocked from where I could post technical content (that is, from work). And so it was. I've noticed lately that the filters were changing and so I attempted to access my little web diary once again only to meet with success. And so here we are. Hopefully I can embark once again on a meaningful dissemination of tips, tricks, and other miscellany. Buckle up.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-19997530215358350612010-12-10T23:41:00.000-06:002010-12-10T23:41:56.208-06:00Sybase ASE vs SQL Server. Hajime!Linchi Shea recently drew a couple of comparisons between Sybase ASE and SQL Server <a href="http://sqlblog.com/blogs/linchi_shea/archive/2010/12/10/sybase-ase.aspx">here</a>. It's been a while since I worked with Sybase, but there were some features that it had that I wish SQL server had.<br />
<br />
<a name='more'></a><br />
<br />
For instance, the ability to mirror files. In Sybase, I can have one logical file mirrored to two or more physical files. This allows me to be able to have a physical disk fail and the database keeps serving data. It also allows me to transparently move a database to new disk without having to take it offline. I'm sure that there are other features that both products can learn from each other on. File-level mirroring always impressed me, though.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com1tag:blogger.com,1999:blog-7273386.post-88376695606411459902010-11-19T14:01:00.000-06:002010-11-19T14:01:39.592-06:00Fortune cookies are usually junk, but...Fortune cookie fortunes are more platitude than anything these days. I'm usually put off by them. I usually want something along the lines of "you will be rewarded for your recent hard work" or "they really <i>are</i> out to get you". So I was pleasantly surprised when I got the following:<br />
<blockquote>Those who endure most are rewarded most.</blockquote>True enough (in bed).Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com1tag:blogger.com,1999:blog-7273386.post-80305945715816387552010-11-09T16:46:00.000-06:002010-11-09T16:46:50.045-06:00Create a database snapshotI've been meaning to write this one for a while. The need arose today to be able to create a database snapshot fairly quickly. Here's what I came up with:<br />
<a name='more'></a><br />
<pre><code>set nocount on
go
declare @timestamp varchar(23) = datediff(second, '1970-01-01', getdate())
declare @file_suffix varchar(50) = '_' + @timestamp + '.snapshot'
declare @database sysname = 'p28TCS1'
declare @sql varchar(max)
select @sql = 'create database ' + quotename(@database + '_' + @timestamp) + ' on '
select @sql += coalesce(stuff((select
',(NAME = ''' + name + ''', FILENAME = ''' + physical_name + @file_suffix + ''')'
from sys.master_files
where database_id = db_id(@database)
and type_desc <> 'LOG'
for xml path ('')), 1, 1, ''), '')
select @sql += ' as snapshot of ' + quotename(@database)
exec( @sql )
select 'Snapshot ' + quotename(@database + '_' + @timestamp) + ' of ' + quotename(@database) + ' created'</code></pre><br />
And remember, <a href="http://blog.semperoccult.us/2010/07/no-warranty-express-or-implied.html">you got what you paid for</a>.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-47897722452341712232010-10-28T16:29:00.000-05:002010-10-28T16:29:31.446-05:00Relog.exe for perfmon slicing and dicing and PAL for reportingSo I'm going through a "how do we make the application better" exercise here at work. We ran a load test last night to see how the system would hold up. I always have perfmon counters running, so I wanted to see how they did during the load test window. Enter relog.<br />
<br />
<a name='more'></a><br />
<br />
All I had to do was: <br />
<code><pre>relog counters.csv -o counters_new.csv -b "10/27/2010 23:00" -e "10/28/2010 02:00" -f csv</pre></code><br />
and I had the counters for the relevant time period. I then fed that to <a href="http://pal.codeplex.com/">PAL</a> and got some nice reports out of it. Sometimes it's the little things. :)Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-67991855568295535162010-10-11T22:39:00.000-05:002010-10-11T22:39:07.396-05:00Validating one article at one subscriberHere's a quick script before I nod off:<br />
<code><pre>use [publisher_db]
go
begin tran
go
exec sp_marksubscriptionvalidation
@publication = N'publication_name,
@subscriber = 'subscriber_server',
@destination_db = 'subscriber_db'
exec sp_article_validation
@publication = N'publication_name',
@article = N'article_name',
@rowcount_only = 2,
@full_or_fast = 2,
@shutdown_agent = 0
go
commit
</pre></code><br />
<br />
I don't think this is exposed through the GUI at all.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-33034475861504215052010-10-08T14:08:00.001-05:002010-10-08T14:11:36.094-05:00Finding last backups with PowershellLast weekend, I did a change control that was in the middle of when we normally do our full backups. As a result, some of the databases didn't get backed up via the normal process. Our data center guys gave me the option of just running the whole thing again, but that would have backed up already backed up databases and given that our retention policy is based on time (and not by number), the backup drive isn't sized to accommodate that. I was also without my script repository (since moved to <a href="http://www.blogger.com/www.dropbox.com">Dropbox</a> so that won't happen again), so I needed a quick way to determine which databases needed to be backed up. Enter powershell:<br />
<br />
<a name='more'></a><br />
<br />
<pre><code>
$instance = new-object Microsoft.SqlServer.Management.Smo.Server "server\instance"
$d = get-date
$instance.Databases | where {($d-$_.LastBackupDate).Days -gt 0} `
| select Name, @{Name="Days since last backup";Expression={($d-$_.LastBackupDate).Days}}
</code></pre><br />
Which I thought was pretty good given that I was in a hotel room in Colorado and I'd been up for almost 24 hours at that point. Powershell, you're my only friend. Lastly, <a href="http://blog.semperoccult.us/2010/07/no-warranty-express-or-implied.html">you get what you pay for</a>.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-31849082996991630092010-08-31T16:32:00.000-05:002010-08-31T16:32:02.400-05:00Getting the TCP port of all instances on a machineSo... we run multiple SQL instances per physical server. There also seems to be a firewall issue between my laptop and the environment that prevents port resolution for those instances. So, I decided to whip up a little Powershell script.<br />
<a name='more'></a><br />
<pre>$results = @()
$MachineObject = new-object ('Microsoft.SqlServer.Management.Smo.WMI.ManagedComputer') .
foreach ($instance in $MachineObject.ServerInstances) {
$return = '' | select Instance, Port
$return.Instance = $instance.name
$return.Port = $instance.ServerProtocols['Tcp'].IPAddresses['IPAll'].IPAddressProperties['TcpPort'].Value
$results += $return
}
$results | format-table
</pre><br />
<a href="http://blog.semperoccult.us/2010/07/no-warranty-express-or-implied.html">Don't run with scissors.</a>Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-32124016240178102182010-08-03T16:55:00.000-05:002010-08-03T16:55:56.699-05:00Get me some articles!So, as I alluded to <a href="http://blog.semperoccult.us/2010/08/small-cursor-usage-trick.html">here</a>, I was doing some work today. Specifically, I was adding articles to a publication. I had an idea that I should be able to come up with a way to add the articles that are missing from the publication. That is, if I have a database with 20 tables and 17 are already articles, then the script should be smart enough to add the 3 that aren't.<br />
<hr/><code><pre>declare tablez cursor for
select schema_name([schema_id]), t.name
from sys.tables t
left join sysarticles a
on t.[object_id] = a.[objid]
where OBJECTPROPERTY([object_id], 'IsMSShipped') = 0 --no system objects
and OBJECTPROPERTY([object_id], 'TableHasPrimaryKey') = 1 --only give me tables that can be replicated, please
and a.[objid] is null --not already an article
open tablez
declare @schema sysname, @table sysname, @fullname sysname
while (1=1)
begin
fetch next from tablez into @schema, @table
if (@@FETCH_STATUS <> 0)
break
set @fullname = @schema + '.' + @table
exec sp_addarticle
@publication = 'Publication',
@article = @fullname,
@source_object = @table,
@destination_table = @table,
@type = 'logbased',
--@schema_option
@destination_owner = @schema,
@status = 16,
@source_owner = @schema
end
close tablez
deallocate tablez
</pre></code><br />
<hr/>The astute among you might wonder why I named the cursor "tablez". I'll present you with two options. <br />
<ol><li>"tables" highlights as a system table in SSMS (a la sys.tables).</li>
<li>I'm l33t.</li></ol><br />
I leave it to the reader to choose. As always, the <a href="http://blog.semperoccult.us/2010/07/no-warranty-express-or-implied.html">standard warning</a> applies.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-14337173260652062802010-08-03T16:43:00.001-05:002010-11-16T14:00:24.628-06:00Small cursor usage trickOkay... everyone knows that cursors are bad. And yet we all use them from time to time. Historically I've written them like this:<br />
<br />
<code><pre>declare @table sysname
declare curs cursor for
select name from sys.tables
fetch next from curs into @table
while (@@fetch_stats = 0)
begin
--do stuff
fetch next from curs into @table
end
close curs
deallocate curs
</pre></code><br />
<br />
While writing some code today, I had this insight:<br />
<br />
<code><pre>declare @table sysname
declare curs cursor for
select name from sys.tables
open curs
while (1=1)
begin
fetch next from curs into @table
if (@@fetch_status <> 0)
break
--do stuff
end
close curs
deallocate curs
</pre></code><br />
With the advantage that I only have to maintain one fetch line as I'm inevitably adding and removing columns from the cursor. I'm sure that I'm not the first to come up with this, but hey... I thought it was nice.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-18239212717151998852010-07-27T06:55:00.000-05:002010-07-27T06:55:12.302-05:00If you never hear that something's impossible...So maybe it's a little early to go off topic, but I thought <a href="http://www.futilitycloset.com/2010/07/21/the-value-of-tardiness/">this</a> was an awesome story. My take away is that Dantzig didn't hear that the problems were unsolved and was thus not dissuaded from working on them. As a result, he solved them. So don't let people tell you what is possible and not; you may just surprise them.Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com0tag:blogger.com,1999:blog-7273386.post-33849134136931520822010-07-19T20:42:00.002-05:002010-07-22T10:52:16.617-05:00Scripting your database for fun and profitInspired by a post by Andy Leonard <a href="http://sqlblog.com/blogs/andy_leonard/archive/2010/07/19/why-does-ssms-generate-create-scripts-with-exec-dbo-sp-executesql.aspx">here</a>, I remembered that I'd been meaning to post a Powershell script that I wrote a while back. What better time than now for an inaugural post!<br />
<a name='more'></a><code></code><br />
<pre>param (
[string] $server = $(Read-Host -prompt "Server"),
[string] $database = $(Read-Host -prompt "Database"),
[string] $directory = $(Read-Host -prompt "Output Directory")
)
$srv = new-object ("Microsoft.SqlServer.Management.Smo.Server") $server
$srv.Initialize() | out-null
if ( $srv.Databases.Contains($database) ) {
$db = $srv.Databases[$database]
}
else {
throw "Database '" + $database + "' not found on '" + $server + "'. Aborting."
}
$scr = new-object "Microsoft.SqlServer.Management.Smo.Scripter"
$scr.Server = $srv
$header_opts = $scr.Options
$header_opts.IncludeDatabaseContext = $false
$header_opts.ToFileOnly = $true
$body_opts = New-Object ("Microsoft.SqlServer.Management.Smo.ScriptingOptions") $header_opts
$header_opts.AppendToFile = $false
$header_opts.IncludeHeaders = $false
$header_opts.IncludeIfNotExists = $true
$header_opts.ScriptDrops = $true
$body_opts.AppendToFile = $true
$body_opts.AnsiPadding = $true
$body_opts.ExtendedProperties = $true
$body_opts.NoCollation = $true
$body_opts.NoCommandTerminator = $false
$body_opts.Permissions = $true
$body_opts.SchemaQualify = $true
$body_opts.ScriptBatchTerminator = $true
$body_opts.ScriptSchema = $true
new-item -path $directory -name "Schema Objects\Views" -type directory -force
foreach ($a in $db.Views | where {$_.IsSystemObject -eq $false}) {
$filename = $directory + '\Schema Objects\views\' + $a.schema + '.' + $a.name + '.view.sql'
$header_opts.FileName = $body_opts.FileName = $filename
$scr.Options = $header_opts
$scr.Script($a)
$scr.Options = $body_opts
$scr.Script($a)
}
new-item -path $directory -name "Schema Objects\Stored Procedures" -type directory -force
foreach ($a in $db.StoredProcedures | where {$_.IsSystemObject -eq $false}) {
$filename = $directory + '\Schema Objects\Stored Procedures\' + $a.schema + '.' + $a.name + '.proc.sql'
$header_opts.FileName = $body_opts.FileName = $filename
$scr.Options = $header_opts
$scr.Script($a)
$scr.Options = $body_opts
$scr.Script($a)
}
new-item -path $directory -name 'Schema Objects\Functions' -type directory -force
foreach ($a in $db.UserDefinedFunctions | where {$_.IsSystemObject -eq $false}) {
$filename = $directory + '\Schema Objects\Functions\' + $a.schema + '.' + $a.name + '.function.sql'
$header_opts.FileName = $body_opts.FileName = $filename
$scr.Options = $header_opts
$scr.Script($a)
$scr.Options = $body_opts
$scr.Script($a)
}
new-item -path $directory -name "Schema Objects\Triggers" -type directory -force
foreach ($table in $db.Tables | where {$_.IsSystemObject -eq $false}) {
foreach ($a in $table.Triggers) {
$filename = $directory + '\Schema Objects\Triggers\' + `
$table.schema + '.' + $table.name + '.' + `
$a.name + '.trigger.sql'
$header_opts.FileName = $body_opts.FileName = $filename
$scr.Options = $header_opts
$scr.Script($a)
$scr.Options = $body_opts
$scr.Script($a)
}
}
</pre><hr />Toss that into a file and run it through Powershell. A word of warning: it will clobber any directory that you point it at for the output. The interesting thing here is that you can get the behavior that Mr. Leonard wants: a guarded 'drop procedure' and a 'create procedure' that's not in an sp_executesql. Have fun...but remember <a href="http://blog.semperoccult.us/2010/07/no-warranty-express-or-implied.html">don't run with scissors!</a>Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com1tag:blogger.com,1999:blog-7273386.post-54021019386372732222010-07-19T20:34:00.001-05:002010-07-19T21:03:53.799-05:00No warranty, express or impliedSo... I'm planning on using this space as a place to talk about things that I find interesting about MS SQL. From time to time, that will involve code/scripts. Right out of the gate, I want to lay the following ground rules:<br />
<br />
<a name='more'></a><br />
<ul><li>Before running any code, you should fully comprehend what it does.</li>
<li>Failing the above, run any code on a system that neither you nor anyone who pays you cares if it starts on fire the instant you run said code.</li>
<li>Even with the above caveats, you absolve me of anything that happens to your system(s) as a result of running provided code.</li>
<li>Don't plagiarize. I want you to use the code that I provide (or at least learn from it), but I also want credit for it.</li>
<li>To crib a line from a sign on <a href="http://davannis.com/">my local pizza joint</a>, if you like what you see here, tell others. If you don't, tell the management.</li>
</ul>Hopefully this will be the least light-hearted post I put on here. Enjoy!Ben Thulhttp://www.blogger.com/profile/09149729879696583244noreply@blogger.com2