Deprecated raiserror detection

All we need is an easy explanation of the problem, so here it is.

I want to upgrade SQL server from 2008 to 2014 versiyon. I checked all of the deprecated features including raiserror syntax. But I have many stored procedures to check. Some of them use new syntax, some of them use old syntax and I need to alter the old syntax from them. How can I check all of the procedures to detect old raiserror syntax?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Below is a PowerShell script example that uses the T-SQL Script DOM parser to parse all existing T-SQL modules in the specified database and display errors if any cannot be parsed for the target SQL version. This will identify discontinued syntax for RAISERROR and any other discontinued T-SQL syntax as well.

$scriptDomAssemblyPath = "C:\Temp\Microsoft.SqlServer.TransactSql.ScriptDom.dll"
$scriptDomNuGetUrl = "https://www.nuget.org/api/v2/package/Microsoft.SqlServer.DacFx.x64/140.3881.1"

# if T-SQL script DOM assembly doesn't already exist at specifed path, download from NuGet and extract assembly from package to $scriptDomAssemblyPath
if(![System.IO.File]::Exists($scriptDomAssemblyPath)) {
    if([String]::IsNullOrWhiteSpace($scriptDomNuGetUrl)) {
        throw "Script DOM assembly not found at $scriptDomAssemblyPath and NuGet package download Url not specified"
    }
    $response = Invoke-WebRequest -Uri $scriptDomNuGetUrl
    if ($response.StatusCode -ne 200) {
        throw "Unable to download Microsoft.SqlServer.TransactSql.ScriptDom NuGet package: $response.StatusCode : $response.StatusDescription"
    }

    $tempZipFilePath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName() + ".zip")
    [System.IO.File]::WriteAllBytes($tempZipFilePath, $response.Content)
    $response.BaseResponse.Dispose()
    $tempUnzipFolderPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
    Expand-Archive -Path $tempZipFilePath -DestinationPath $tempUnzipFolderPath
    $tempZipFilePath | Remove-Item
    Move-Item "$tempUnzipFolderPath\lib\net46\Microsoft.SqlServer.TransactSql.ScriptDom.dll" $scriptDomAssemblyPath
    $tempUnzipFolderPath | Remove-Item -Recurse
}

Add-Type -Path $scriptDomAssemblyPath

# use the appropriate TSqlParser version for target SQL version (TSql120Parser for SQL Server 2014)
$parser = New-Object Microsoft.SqlServer.TransactSql.ScriptDom.TSql120Parser($true)
$parseErrors = New-Object System.Collections.Generic.List[Microsoft.SqlServer.TransactSql.ScriptDom.ParseError]

# parse existing T-SQL modules in database
$connectionString = "Data Source=YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI;Application Name=Parse Modules"
$connection = New-object System.Data.SqlClient.SqlConnection($connectionString);
$command = New-object System.Data.SqlClient.SqlCommand("SELECT OBJECT_SCHEMA_NAME(object_id) AS SchemaName, OBJECT_NAME(object_id) AS ObjectName, definition FROM sys.sql_modules;", $connection);
$connection.Open()
$reader = $command.ExecuteReader()
while ($reader.Read()) {

    $scriptReader = New-Object System.IO.StringReader($reader["definition"])
    $frament = $parser.Parse($scriptReader, [ref]$parseErrors)
    if($parseErrors.Count -gt 0) {

        Write-Host "error parsing [$($reader["SchemaName"])].[$($reader["ObjectName"])]"
        foreach ($parseError in $parseErrors) {
            Write-Host "`t$($parseError.Message)"
        }
    }

}
$reader.Close()
$connection.Close()

Method 2

According to Discontinued Database Engine Functionality in SQL Server 2012, the deprecated version of raiserror is

RAISERROR integer 'string'.

Notice there is no parenthesis and there is a number after RAISERROR.

Using @HandyD’s approach as a starting point, you could do something like this (sqltable simulates what is returned from INFORMATION_SCHEMA.ROUTINES).

--demo setup
Declare @sqltable table(sqlvar varchar(max))
Declare @CrLf varchar(2) = char(13) + char(10)

insert into @sqltable(sqlvar) values('Raiserror 50000 ''This is old syntax'')')
insert into @sqltable(sqlvar) values('Raiserror 
50000 ''This is old syntax where the command is on multiple lines'')')
insert into @sqltable(sqlvar) values('RAISERROR (''This is new syntax'',16,0)')

--the query
select * from @sqltable where replace(replace(sqlvar,@CrLf,''),' ','') like '%raiserror[0-9]%'

| sqlvar                                                                         |
|--------------------------------------------------------------------------------|
| Raiserror 50000 'This is old syntax')                                          |
| Raiserror   50000 'This is old syntax where the command is on multiple lines') |

Method 3

Use this script to identify any procedures or functions using the old syntax:

SELECT ROUTINE_NAME
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%RAISERROR%'

This needs to be executed in the context of the database you’re checking. For multiple databases, you will need to run it against each database.

More info on INFORMATION_SCHEMA.ROUTINES.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply