SQL Interview Questions

Complimentary to the blog post on Qindi (Cindy) Zhang

SQL interview question bank:

On candidate’s basic understanding on data structure and SQL fundamentals:

  1. Can you interchange where and having clause?
  2. What is a correlated sub-query?

On candidate’s actual hands on SQL experience:

  1. How to perform unpivot in SQL?
  2. How large is the dataset you typically query against? What are some of the things you do to improve query efficiency?

On candidate’s business exposure and understanding:

  1. What is a business case where you need to use full join?
  2. How do you handle missing days in a transaction report if dashboard users want this information captured and reflected?


For the technical interview, it’s best to combine some actually code writing with conceptual questions  such as above. That way you as an interviewer can evaluate how familiar the candidate is with the basics, how comfortable she is at writing code, how much of her knowledge is from book vs. from practice. And furthermore, how well the analyst is able to grasp the underlying business requirement and deliver the analytics product that satisfies stakeholder’s need.
Interviewers, I hope this gives you an easy start!

SQL: Select Nth rank of something. Three approaches.

Common Question on Forums, how to get the 3rd highest salary or similar. Also a common job interview question perhaps?
I am using the AdventureWorksDW2012 database. Tests were done with SQL Server 2012 SP2

I run each query twice. Once with the base table and once with a covering Index.
Here is the covering Index:

CREATE NONCLUSTERED INDEX _E_DimEmployee_BaseRate
ON [dbo].[DimEmployee] ([BaseRate])
INCLUDE ([FirstName],[LastName])

Correlated subquery:

SELECT FirstName, LastName, BaseRate
FROM DimEmployee e
WHERE (SELECT COUNT(DISTINCT BaseRate)
    FROM DimEmployee p WHERE e.BaseRate <= p.BaseRate) = 4

Why is this a good answer? It’s not really but this will work on any SQL implementation.
It’s fairly slow, it will do a lot of look ups.  The subquery is evaluated every time a row is processed by the outer query. This query uses dense ranking and can return multiple rows.

Here are the IO and time stats.
Without Index:
Table ‘Worktable’. Scan count 564, logical reads 1337, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘DimEmployee’. Scan count 54, logical reads 2646, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
elapsed time = 20 ms.

With covering Index:
Table ‘Worktable’. Scan count 349, logical reads 907, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table ‘DimEmployee’. Scan count 54, logical reads 233, physical reads 0, read-ahead reads 4, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
elapsed time = 13 ms.

Double Order By with TOP statement:

SELECT TOP 1 FirstName, LastName, BaseRate
FROM ( SELECT TOP 4 FirstName, LastName, BaseRate
    FROM DimEmployee ORDER BY BaseRate DESC) AS MyTable
ORDER BY BaseRate ASC;


Why is this a good answer? Because it is an easy syntax to remember.
Let’s look at the subquery, which returns the N highest salaries in the DimEmployee table in descending order. Then, the outer query will re-order those values in ascending (default) order, this means the Nth highest salary will now be the topmost salary. Keep in mind that the TOP statement is MS SQL server specific. MySQL would use LIMIT 1 for instance. In addition this solution cannot do DENSE ranking and only returns one row even if two employees share the same BaseRate.

Edit June 2015: The addition of LIMIT/OFFSET on SQL Server 2012 made answer obsolete. The syntax for LIMIT/OFFSET has been added on the bottom of this post.

Here are the IO and time stats.
Without Index:
Table ‘DimEmployee’. Scan count 1, logical reads 49, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
elapsed time = 5 ms.

With covering Index:
Table ‘DimEmployee’. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
elapsed time = 0 ms.

Use Windowing function:

SELECT FirstName, LastName, BaseRate
FROM (SELECT FirstName, LastName, BaseRate, DENSE_RANK() OVER (ORDER BY BaseRate DESC) Ranking
FROM DimEmployee) AS MyTable
WHERE Ranking = 4

Why is this a good answer? Because it performs the best – performance is king. The Syntax is also ANSI SQL however of the “Big 3” only Oracle and MS are using it. In addition you can chose to use ROW_NUMBER, DENSE_RANK or regular RANK.

Here are the IO and time stats.
Without Index:
Table ‘DimEmployee’. Scan count 1, logical reads 49, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
elapsed time = 2 ms.

With covering Index:
Table ‘DimEmployee’. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
elapsed time = 0 ms.

Edit: June 2015
Use OFFSET (SQL Server 2012):

SELECT FirstName, LastName, BaseRate
FROM DimEmployee e
ORDER BY BaseRate DESC
OFFSET 3 ROWS
FETCH NEXT 1 ROWS ONLY

Why is this a good answer? Because similar Syntax exists on the other platforms.
Performance wise it runs as well as the windowing solution.

Microsoft Access Database Engine: External table is not in the expected format. (when opening an excel file that is read locked)

Another quick and dirty post. Because it took me over an hour to get to the issue.

VBS Error: Microsoft Access Database Engine: External table is not in the expected format.
This error occurs upon opening the ADODB.Connection

Turns out the issue was because I had read some stuff of the excel via OpenTextFile, previously but forgot to close that.
So the error occurred because the file was read locked and not because “External table is not in the expected format.”
Shows just how much time you could save with the “right” error message.

Note1: This is most likely just one possible cause of this generic error message.
Note2: if the file actually doesn’t exist the error message is much better:
Microsoft Access Database Engine: The Microsoft Access database engine could not find the object 'Scope Information$A1:B65535'. Make sure the object exists and that you spell its name and the path name correctly. If 'Scope Information$A1:B65535' is not a local object, check your network connection or contact the server administrator.

Getting the Language pack lp.cab out of the downloadable exe files.

You can get them out by running the EXE, as it extracts/creates the cab file. In my case the German package windows6.1-kb2483139-x86-de-de_acb9b88b96d432749ab63bd93423af054d23bf81.exe
However the issue, I had found, is that the EXE quits very fast and deletes the cab file right away.
I considered running PSSuspend against it, but the issue is that this would still be a game, as the cab file gets built slowly, but deleted very quickly if the OS refuses the install.
So the next best solution is NTFS permissions, simply create a temporary DACL for EVERYONE with DENY for “Delete Folders and Files”.
This will leave your lp.cab ready for the grabbin :)

Screw it, I am going to search all tables, all columns!

Ever had the need to find out where data is stored in your MS SQL Database?
I sometimes do and I find it often faster to simply search every table and every column within these table than to try and hunt down the schema definitions. I get a coffee while the script crunches away.  The @SearchStrColumnName option is there mostly for when you search integers, as you may get too many false positives.

Edit: GitHub Gist works awesome, will have to do that for the previous posts too! Just paste the URL, and wordpress will do the rest, in this case display a fully highlighted T-SQL code.
Edit 4/8/2013 – @SearchStrColumnName wasn’t properly escaped before and this parameter didn’t really work.
Edit 4/9/2013 – Added parameter @FullRowResult, this will cause it to return the full row for each hit. This is usefull when you need to lookup or find related info to the search term.
Edit 4/12/2013 – Added parameter @SearchStrTableName, to limit in what tables we are going to search.
Edit 5/2/2013 – Now also searching in type uniqueidentifier (GUID)
Edit 5/22/2013 – Additional numeric data types will be searched.
Edit 1/7/2014 – Can now also search timestamp value (known as rowversion)
Edit 4/18/2014 – Added a Top parameter that works together with @FullRowResult. This is to help limit the return if a search string is found in a table too often


/* Reto Egeter, fullparam.wordpress.com */
DECLARE @SearchStrTableName nvarchar(255), @SearchStrColumnName nvarchar(255), @SearchStrColumnValue nvarchar(255), @SearchStrInXML bit, @FullRowResult bit, @FullRowResultRows int
SET @SearchStrColumnValue = '%searchthis%' /* use LIKE syntax */
SET @FullRowResult = 1
SET @FullRowResultRows = 3
SET @SearchStrTableName = NULL /* NULL for all tables, uses LIKE syntax */
SET @SearchStrColumnName = NULL /* NULL for all columns, uses LIKE syntax */
SET @SearchStrInXML = 0 /* Searching XML data may be slow */
IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results
CREATE TABLE #Results (TableName nvarchar(128), ColumnName nvarchar(128), ColumnValue nvarchar(max),ColumnType nvarchar(20))
SET NOCOUNT ON
DECLARE @TableName nvarchar(256) = '',@ColumnName nvarchar(128),@ColumnType nvarchar(20), @QuotedSearchStrColumnValue nvarchar(110), @QuotedSearchStrColumnName nvarchar(110)
SET @QuotedSearchStrColumnValue = QUOTENAME(@SearchStrColumnValue,'''')
DECLARE @ColumnNameTable TABLE (COLUMN_NAME nvarchar(128),DATA_TYPE nvarchar(20))
WHILE @TableName IS NOT NULL
BEGIN
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME LIKE COALESCE(@SearchStrTableName,TABLE_NAME)
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(OBJECT_ID(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)), 'IsMSShipped') = 0
)
IF @TableName IS NOT NULL
BEGIN
DECLARE @sql VARCHAR(MAX)
SET @sql = 'SELECT QUOTENAME(COLUMN_NAME),DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(''' + @TableName + ''', 2)
AND TABLE_NAME = PARSENAME(''' + @TableName + ''', 1)
AND DATA_TYPE IN (' + CASE WHEN ISNUMERIC(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@SearchStrColumnValue,'%',''),'_',''),'[',''),']',''),'-','')) = 1 THEN '''tinyint'',''int'',''smallint'',''bigint'',''numeric'',''decimal'',''smallmoney'',''money'',' ELSE '' END + '''char'',''varchar'',''nchar'',''nvarchar'',''timestamp'',''uniqueidentifier''' + CASE @SearchStrInXML WHEN 1 THEN ',''xml''' ELSE '' END + ')
AND COLUMN_NAME LIKE COALESCE(' + CASE WHEN @SearchStrColumnName IS NULL THEN 'NULL' ELSE '''' + @SearchStrColumnName + '''' END + ',COLUMN_NAME)'
INSERT INTO @ColumnNameTable
EXEC (@sql)
WHILE EXISTS (SELECT TOP 1 COLUMN_NAME FROM @ColumnNameTable)
BEGIN
PRINT @ColumnName
SELECT TOP 1 @ColumnName = COLUMN_NAME,@ColumnType = DATA_TYPE FROM @ColumnNameTable
SET @sql = 'SELECT ''' + @TableName + ''',''' + @ColumnName + ''',' + CASE @ColumnType WHEN 'xml' THEN 'LEFT(CAST(' + @ColumnName + ' AS nvarchar(MAX)), 4096),'''
WHEN 'timestamp' THEN 'master.dbo.fn_varbintohexstr('+ @ColumnName + '),'''
ELSE 'LEFT(' + @ColumnName + ', 4096),''' END + @ColumnType + '''
FROM ' + @TableName + ' (NOLOCK) ' +
' WHERE ' + CASE @ColumnType WHEN 'xml' THEN 'CAST(' + @ColumnName + ' AS nvarchar(MAX))'
WHEN 'timestamp' THEN 'master.dbo.fn_varbintohexstr('+ @ColumnName + ')'
ELSE @ColumnName END + ' LIKE ' + @QuotedSearchStrColumnValue
INSERT INTO #Results
EXEC(@sql)
IF @@ROWCOUNT > 0 IF @FullRowResult = 1
BEGIN
SET @sql = 'SELECT TOP ' + CAST(@FullRowResultRows AS VARCHAR(3)) + ' ''' + @TableName + ''' AS [TableFound],''' + @ColumnName + ''' AS [ColumnFound],''FullRow>'' AS [FullRow>],*' +
' FROM ' + @TableName + ' (NOLOCK) ' +
' WHERE ' + CASE @ColumnType WHEN 'xml' THEN 'CAST(' + @ColumnName + ' AS nvarchar(MAX))'
WHEN 'timestamp' THEN 'master.dbo.fn_varbintohexstr('+ @ColumnName + ')'
ELSE @ColumnName END + ' LIKE ' + @QuotedSearchStrColumnValue
EXEC(@sql)
END
DELETE FROM @ColumnNameTable WHERE COLUMN_NAME = @ColumnName
END
END
END
SET NOCOUNT OFF
SELECT TableName, ColumnName, ColumnValue, ColumnType, COUNT(*) AS Count FROM #Results
GROUP BY TableName, ColumnName, ColumnValue, ColumnType

view raw

Search All.sql

hosted with ❤ by GitHub

Run a script when windows resumes from suspend/sleep via WMI Event Consumer

You may want to achieve some power savings, but it turns out some services or programs misbehave.
One way around this issue is to run a script when the machine resumes. We can achieve this via two OS native methods:
Task Scheduler on Vista+
WMI Event consumer on Win2K+

I am going to only show my approach for the WMI Event, but I wanted to preempt the comments about task scheduler, yes – I am aware, but there are still two advantages to running it via WMI.
Works for all Windows flavors & it is embedding the script code within WMI, so no visibility to end users that they can modify or disable.
Both methods will run the script/code as SYSTEM, which can be a problem when your issues are related to GUI apps, such as Outlook/Exchange connectivity. This limitation does not exist with the excellent 1E NightWatchman that can run scripts as the logged in user. Without NightWatchman there is no way around programming WTSEnumerateSessions () -> WTSQueryUserToken() -> CreateEnvironmentBlock() -> CreateProcessAsUser() and actually compiling an executable that our script would have to call. Maybe I will post an actual example if some requests do come in.

The main obstacle I found with WMI scripts is the deployment. Likely you want to deploy this solution on a number of machines. The classical way would be to write a MOF file and compile that via mofcomp. I decided to actually create my instances via a VBS script. Note that no matter which approach, the Instances will have to be created while running in SYSTEM. Any consumers created as a regular user would only execute if that user is specifically logged in and is a local admin.

This script will restart a specified Service on your machine. As an example only I am restarting “Wireless Zero Configuration” or in short WZCSVC which exists on all XP machines.
Each time this service stops/starts it will write into the application event log as source EAPOL. This is how you can verify the process worked.

Interesting bits worth noting from the script:
The script will force to use the 64bit version of Wscript when available, even if this script is launched via 32bit process such as the SCCM client. I do this via the WMI method Win32_Process whilst forcing to connect to the 64 bit WMI.
The following code snippet is relevant: objCtx.Add “__ProviderArchitecture”, 64 ‘Load 64bit version of WMI if available. In fact I should create another blog post just on how to escape the bit-ness via WMI of a process.

Use of vbNewLine for the script text. This is needed as VBScript is line aware and I have to somehow add the new line command into WMI. Note that vbCrLf doesn’t work for this scenario.


' Reto Egeter, fullparam.wordpress.com, Feb 2012
' Streamlined process. Installs correctly for x86, x64 and sandboxed 6432WOW.
Set wShe = CreateObject("WScript.Shell")
DebugMode = True
'No Security Warnings
set oEnv = wShe.Environment("PROCESS")
oEnv("SEE_MASK_NOZONECHECKS") = 1 'This prevent Security Zone checking for the period of execution.
Set objCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
objCtx.Add "__ProviderArchitecture", 64 'Load 64bit version of WMI if available.
Set objLocator = CreateObject("Wbemscripting.SWbemLocator")
'Run Script in 64Bit if 64Bit OS detected.
If oEnv("PROCESSOR_ARCHITECTURE") = "x86" And oEnv("PROCESSOR_ARCHITEW6432") <> "" Then
Set objServices = objLocator.ConnectServer("","root\cimv2","","",,,,objCtx)
Set objShare = objServices.Get("Win32_Process")
Set objInParam = objShare.Methods_("Create").inParameters.SpawnInstance_()
'Add the input parameters.
objInParam.Properties_.Item("CommandLine") = "WScript.exe " & WScript.ScriptFullName
objInParam.Properties_.Item("CurrentDirectory") = Left(WScript.ScriptFullName,InStrRev(WScript.ScriptFullName,"\")-1)
'Execute the method and obtain the return status.
'The OutParameters object in objOutParams is created by the provider.
Set objOutParams = objServices.ExecMethod("Win32_Process", "Create", objInParam)
'List OutParams
If debugmode = "True" Then
Select Case objOutParams.ReturnValue
Case 0 WScript.Echo "Command Executed"
Case 2 WScript.Echo "Access denied"
Case 3 WScript.Echo "Insufficient privilege"
Case 9 WScript.Echo "Path not found"
Case 21 WScript.Echo "Invalid parameter"
Case Else WScript.Echo "Unknown failure"
End Select
End If
WScript.Quit(0)
End If
'Ensure Running as SYSTEM
Set WshNetwork = WScript.CreateObject("WScript.Network")
If WshNetwork.UserName <> "SYSTEM" Then
If DebugMode = True Then WScript.Echo "Current User Name: """ & WshNetwork.UserName & """ This needs to run as SYSTEM."
wShe.LogEvent 4, Now & " Installing of the 1E WMI resume script (SYSTEM user) on this machine failed, install script was not run as SYSTEM"
WScript.Quit (1)
End If
Set objServices = objLocator.ConnectServer("","root\subscription","","",,,,objCtx)
'Create new ActiveScriptEventConsumer
Set newActiveScriptEventConsumer = objServices.Get("ActiveScriptEventConsumer").SpawnInstance_
newActiveScriptEventConsumer.Name = "RestartService"
newActiveScriptEventConsumer.ScriptingEngine = "VBScript"
newActiveScriptEventConsumer.ScriptText = "' Reto Egeter, Feb 2012" & vbNewLine & ""&_
"' Script that will stop and start the wireless service. This will write an event into the application log" & vbNewLine & ""&_
"" & vbNewLine & ""&_
"strComputer = ""."" " & vbNewLine & ""&_
"Set objWMIService = GetObject(""winmgmts:"" & ""{impersonationLevel=impersonate}!\\"" & strComputer & ""\root\cimv2"") " & vbNewLine & ""&_
"" & vbNewLine & ""&_
"StopService(""WZCSVC"")" & vbNewLine & ""&_
"QueryServiceStopped(""WZCSVC"")'Waiting until service is stopped." & vbNewLine & ""&_
"StartService(""WZCSVC"") " & vbNewLine & ""&_
"" & vbNewLine & ""&_
"" & vbNewLine & ""&_
"Function StartService(SrvName) " & vbNewLine & ""&_
" Dim colServiceList, objService " & vbNewLine & ""&_
" Set colServiceList = objWMIService.ExecQuery(""Select * from Win32_Service where Name='"" & srvName & ""'"") " & vbNewLine & ""&_
" For Each objService in colServiceList " & vbNewLine & ""&_
" errReturn = objService.Change( , , , , ""Automatic"") 'Enabling Autostart." & vbNewLine & ""&_
" StartService = objService.StartService() " & vbNewLine & ""&_
" Next " & vbNewLine & ""&_
"End Function " & vbNewLine & ""&_
"" & vbNewLine & ""&_
"Function StopService(SrvName) " & vbNewLine & ""&_
" Dim colServiceList, objService " & vbNewLine & ""&_
" Set colServiceList = objWMIService.ExecQuery(""Select * from Win32_Service where Name='"" & srvName & ""'"") " & vbNewLine & ""&_
" For Each objService in colServiceList " & vbNewLine & ""&_
" StopService = objService.StopService() " & vbNewLine & ""&_
" Next " & vbNewLine & ""&_
"End Function " & vbNewLine & ""&_
"" & vbNewLine & ""&_
"Function QueryServiceStopped(SrvName) 'Until it is not stopping" & vbNewLine & ""&_
" Dim colSrvList, objSrvc " & vbNewLine & ""&_
" Set colSrvList = objWMIService.ExecQuery(""Select * from Win32_Service where Name='"" & srvName & ""'"") " & vbNewLine & ""&_
" For Each objSrvc in colSrvList " & vbNewLine & ""&_
" If objSrvc.InterrogateService() = 4 Then '4 means stopping" & vbNewLine & ""&_
" QueryServiceStopped(SrvName) 'Recursive Function" & vbNewLine & ""&_
" End If" & vbNewLine & ""&_
" Next " & vbNewLine & ""&_
"End Function "
Set newActiveScriptEventConsumerObj = newActiveScriptEventConsumer.Put_ ' Save the new ActiveScriptEventConsumer
wShe.LogEvent 4, Now & " Installing of the FullParam WMI resume script (SYSTEM user): Created ActiveScriptEventConsumer"
'Create new EventFilter
Set newEventFilter = objServices.Get("__EventFilter").SpawnInstance_
newEventFilter.EventNamespace = "root\cimv2"
newEventFilter.Name = "Resume"
newEventFilter.Query = "Select * from Win32_PowerManagementEvent WITHIN 1 WHERE EventType = 7 " 'Check Every Second for Power Event Resume
newEventFilter.QueryLanguage = "WQL"
Set newEventFilterObj = newEventFilter.Put_ ' Save the new EventFilter
wShe.LogEvent 4, Now & " Installing of the 1E WMI resume script (SYSTEM user): Created __EventFilter"
'Create new FilterToConsumerBinding
Set newFilterToConsumerBinding = objServices.Get("__FilterToConsumerBinding").SpawnInstance_
newFilterToConsumerBinding.Filter = newEventFilterObj
newFilterToConsumerBinding.Consumer = newActiveScriptEventConsumerObj
Set newFilterToConsumerBindingObj = newFilterToConsumerBinding.Put_ ' Save the new FilterToConsumerBinding
wShe.LogEvent 4, Now & " Installing of the 1E WMI resume script (SYSTEM user): Created __FilterToConsumerBinding"
wShe.LogEvent 4, Now & " Installing of the 1E WMI resume script (SYSTEM user): Finished Installing the script on this machine"
oEnv.Remove("SEE_MASK_NOZONECHECKS")

Windows bitlocker drive encryption recovery key entry

Seen this discussed, and actually the DOS based bios update tool warns about it, but for whatever reasons the Lenovo team decided not to show that warning on the Windows tool.

As I did not have access to the recovery key due to it being the weekend and the internal IT being unavailable I had to look at alternative recovery solutions. The Windows bootup greets me with the message:
Windows Bitlocker Drive Encryption Recovery Key Entry
Enter the recovery key for this drive

Obviously the big question is: Will restoring to the old Bios version do the trick? The answer is YES.
Now let’s hope your vendor has a DOS/CD-ROM/Floppy disk based alternative to modify the bios, because that is what you will need as you are locked out of your Windows.

Since I do not own a CDR-Drive, I’ve chosen to use a USB stick instead.
I’ve used XBoot for this purpose and found it worked well, here is the process:
1.) Get XBoot and open the program.
2.) Drag and drop your .iso file into it, and in the wizard select: Grub4dos ISO Emulation
Unfortunately I’ve found you can only add one Grub4dos ISO Emulation .iso file successfully.
3.) Boot up the affected machine via this USB key and downgrade the BIOS.
4.) Success? If not you may have chosen the wrong bios version and want to replace the created .iso file on your memory stick with another bios version.
5.) Once you can boot again, Suspend Bitlocker encryption via the Control Panel, re-do the Bios upgrade and after the reboot resume Bitlocker.

Remove SQL block comments via regex

My blog is a bit quiet sometimes, and this is because I usually want to post big projects.
However I think I should also post small code snippets as they may help somebody too.
Trevor just asked about how to detect SQL block statements via regex, and I remember I had to use such a regex in order to trim a massive SQL query into 8000 chars for a classic SCCM report.
Use this Perl regex to detect SQL block comments
/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/

This will not detect comments denoted by -- which you should not use anyway :)

My next bigger project is to show WMI Event Consumer driven scripts, run scripts on resume and on PC idle btw.