PAL and SQLDiag with SQL Server 2012
24 May 12 11:56 PM | MartinBell | 1 comment(s)

We’ve had a great week at SQL Relay so far I have organised one event and helped run a second and spoken at 2 others. I still have presentations at the final legs in London to go and I'm looking forward to them. As part of my presentation I talk about running PAL with SQL Server 2012. The SQL 2005/2008 threshold file can be used against a server running SQL Server 2012, so your Performance Data Collection Set that is imported from the PAL threshold file is still ok.

If you don’t like using logman to start your Performance Counter collection (real DBA don’t use the Perfmon GUI Smile), then you may look towards SQLDiag to collect your SQL Trace and Performance Counter data. Anyone brave enough to hand craft their own SQLDiag configuration files are hopefully already seeking counselling. I use the SQLDiag Configuration Tool (SDCT) available on codeplex. Unfortunately the last time the project was updated was 20 May 2011 and does not list SQL Server 2012 as a supported option. Luckily the only issue I have found with the generated configuration files is the need to change the SQL Server version number for (say) 10.50 to 11. i.e. the line like:

<Instance name="*" windowsauth="true" ssver="10.50" user="">

changes to:

<Instance name="*" windowsauth="true" ssver="11" user="">

PAL will collect around 71 performance counters for a single instance of SQL Server. Configuring these with SDCT is still quite a tedious job, so I created a template which includes all the counters in the PAL Threshold file. A copy of _ss_PAL.xml can be found here.

To install copy the file to
C:\Program Files (x86)\Taylor Made Enterprises\SQLDiag Configuration Tool\PerfmonTemplates\nn and give it a name such as _ss_PAL.xml. This will then appear in the available templates for example if you configure a collection of SQL Server 2008 R2 counters put it in the C:\Program Files (x86)\Taylor Made Enterprises\SQLDiag Configuration Tool\PerfmonTemplates\10 directory.       



Unfortunately I don’t know of a way to add additional buttons to the front screen, but you can change the underlying configuration file e.g. SQLDiag1050.XML for SQL Server 2008 R2 in C:\Program Files (x86)\Taylor Made Enterprises\SQLDiag Configuration Tool\Configurations (although you probably want to do this for the SQL Server 2005 file!) to generate SQL Server 2012 configuration files without having edit the configuration file afterwards. To do this create the following directories
C:\Program Files (x86)\Taylor Made Enterprises\SQLDiag Configuration Tool\PerfmonTemplates\11
C:\Program Files (x86)\Taylor Made Enterprises\SQLDiag Configuration Tool\TraceTemplates\11
(you may just want to copy the corresponding …\10 directories). The configuration file <here> will always create SQL Server 2012 configuration files without you having to change the ssver attribute, This configuration goes one step further and make the PAL Performance Counter set the default. This collection will also collect the SQL Trace completion events which are useful when aggregating information from trace files when pinpointing poorly performing code.



It's interesting that the new configuration file is recognised as being for SQL Server Denali. The template (_Performance_Aggregation.xml) to collect this information can be found here place it in the appropriate TraceTemplates directory.

Filed under: , ,
Changing Server Side Trace Scripts
20 May 12 07:38 PM | MartinBell | with no comments

Although SQL Trace is marked started it’s deprecation stage, it will be around for quite some time to come. Therefore I thought I would share a couple of changes I make to server side traces  when I use them. (It also means I will always have somewhere to find the code without writing it from scratch!)

In the past when you scripted a service side trace in SQL Profiler, the script generated would contain a comment containing the statements required to stop and close the trace.

This may have been removed because you needed to change the script and put in the correct TraceID parameters, therefore limiting the value of the suggested code. If it fits your circumstances (i.e. no other Server Side traces being run on the system) you could use the following generic code to stop the most recent trace.~

DECLARE @TraceID int ;
SET @TraceID  = ( SELECT MAX(traceid)/
FROM sys.fn_trace_getinfo(0) )  ;
SELECT @TraceID ;
IF @TraceID IS NOT NULL
BEGIN
    EXEC sp_trace_setstatus @TraceID, 0
    EXEC sp_trace_setstatus @TraceID, 2
END ;
GO

If you are using the Default Trace then you may get the following message if you try to stop it.

Msg 19070, Level 16, State 1, Procedure sp_trace_setstatus, Line 1
The default trace cannot be stopped or modified. Use SP_CONFIGURE to turn it off.

Therefore you may want to amend the above script to avoid the trace with a TraceID of 1.

DECLARE @TraceID int ;
SET @TraceID  = ( SELECT MAX(traceid)
FROM sys.fn_trace_getinfo(DEFAULT)
WHERE traceid > 1 ) ;
SELECT @TraceID ;
IF @TraceID IS NOT NULL
BEGIN
    EXEC sp_trace_setstatus @TraceID, 0 ;
    EXEC sp_trace_setstatus @TraceID, 2 ;
END ;
GO       

An alternate method to identify the Trace to stop could be to identify a unique part of the filename. Filename is property 2 returned by fn_trace_getinfo.

DECLARE @TraceID int ;
SET @TraceID = ( SELECT traceid
FROM sys.fn_trace_getinfo(DEFAULT)
WHERE Property = 2
AND CAST(VALUE as varchar(max)) LIKE 'T:\TraceFiles\Trace_%' )
SELECT @TraceID ;
IF @TraceID IS NOT NULL
BEGIN
    EXEC sp_trace_setstatus @TraceID, 0 ;
    EXEC sp_trace_setstatus @TraceID, 2 ;
END ;
GO       
 

Ideally the trace files will be places on a drive on the server that is not going to cause resource conflicts when writing to any of the database files. When you script the trace definition the filename is one of the things you have to enter yourself. The command that is scripted is:

exec @rc = sp_trace_create @TraceID output, 0, N'InsertFileNameHere', @maxfilesize, NULL


If you hard code this to be a specific file then the trace will fail to start if the file already exists e.g.

With the following line in your script:

exec @rc = sp_trace_create @TraceID output, 0, N'T:\TraceFiles\Trace_Test', @maxfilesize, NULL

If you run the trace script a second time you will see the error:

Windows error occurred while running SP_TRACE_CREATE. Error = 0x80070050(failed to retrieve text for this error. Reason: 15100).
Msg 19062, Level 16, State 1, Procedure sp_trace_create, Line 1
Could not create a trace file.


To overcome this you can make the file unique by adding a date and time.

DECLARE @tracefilename nvarchar(245) ;
SET @tracefilename = N'T:\TraceFiles\Trace_' + REPLACE(REPLACE(REPLACE(CONVERT(varchar(19),  GETDATE(), 120 ),' ','_'),':',''),'-','') ;
EXEC @rc = sp_trace_create @TraceID output, 0, @tracefilename, @maxfilesize, NULL
 ;~

The scripted value for @maxfilesize is a paltry 5MB. You may want to change this to be a little bigger, especially as the default options (second parameter is 0) does not to use trace file rollover.

Anyone who has looked up what the fifth parameter is (set to NULL) will know this is a stop time. If you know how long the script should run, you will not need to stop the trace yourself if you set the parameter to an absolute date and time.

DECLARE @tracefilename nvarchar(245) ;
DECLARE @stoptime datetime ;
DECLARE @timeintervalsecs int ;
SET @timeintervalsecs = 600 ; /* 10 minutes */
SET @stoptime  = DATEADD( ss, @timeintervalsecs, getdate() ) ;
SET @tracefilename = N'T:\TraceFiles\Trace_' + REPLACE(REPLACE(REPLACE(CONVERT(varchar(19),  GETDATE(), 120 ),' ','_'),':',''),'-','') ;

EXEC @rc = sp_trace_create @TraceID output, 0, @tracefilename, @maxfilesize, @stoptime ;
if (@rc != 0) goto error ;

Whilst writing this article I have noticed a “bug” with the Default Profiler Template, it seems to have always been present and noone has bothered to log it. To see it go to http://tinyurl.com/DefaultProfilerTraceBug*

Changing SQL Server Port with Powershell
07 May 12 05:48 PM | MartinBell | 1 comment(s)

The other week, we were fortunate to have Mark Broadbent (blog\twitter) as a guest speaker at the Leeds SQL Server User Group. he did a great presentation on using Windows Server Core and SQL Server. If you haven’t taken time to learn Powershell then this could be the best reason to do so. Of course if you are already have your own toolbox of Powershell scripts to administer SQL Server on other editions of Windows, moving to Windows Core will be a doddle!

I have previously posted blogs about stopping/starting SQL Server using Powershell, and also enabling protocols with a Powershell script so when Mark mentioned Powershell as one option to change the TCP/IP port for an SQL Server Instance I thought I would write my own.

I incorporated into the scripts a check to make sure the instigator was a “real administrator” and also to prompt the user to start/restart the SQL Server instance to allow the changes to take effect.

The script can be found here.

Filed under: ,
sp_refreshview
15 February 12 08:42 PM | MartinBell | with no comments

The other Friday we had a very successful go live of a new production box… apart from a couple of minor things. Some of the reports that were being produced ran significantly slower and the other was a SQL Agent Job on a third party server suddenly stopped working.

As the reports were not mission critical they got shunted to the end of the queue, so the SQL Agent job was top priority on Monday morning.

The SQL Agent package was failing after about 20 seconds with the error messages

Msg 65535, Sev 16, State 1: SQL Server Network Interfaces: Server doesn't support requested protocol [xFFFFFFFF]. [SQLSTATE 42000]

Msg 7412, Sev 16, State 1, Line 14 : OLE DB provider "SQLNCLI10" for linked server "<Linked Server>" returned message "Login timeout expired". [SQLSTATE 01000]

Msg 7412, Sev 16, State 1, Line 14 : OLE DB provider "SQLNCLI10" for linked server "<Linked Server>" returned message "A network-related or instance-specific error has occurred while establishing a connection to SQL Server. Server is not found or not accessible. Check if instance name is correct and if SQL Server is configured to allow remote connections. For more information see SQL Server Books Online.". [SQLSTATE 01000]

I tracked down the query that failed and although the linked server had been changed, I check that I could browse it in SSMS and do simple SELECT queries using the objects used in the query. I could also execute the INSERT…SELECT statement that failed in SSMS. If a problem is easily re-creatable it is quickly solved, so I created a test job and the SELECT queries still worked but the INSERT..SELECT statement failed when I included any view that referenced the linked server. This was turning out to be very annoying especially as the linked server used a specific login, I could not see why this should fail only in a SQL Agent job.

Bingoogling the error message turned up the usual suspects such remote logins not being enabled, firewall issues and protocols not being enabled. Despite being pretty sure these weren’t the cause I checked each of them out and dismissed each one. To quote Sherlock Holmes “When you have eliminated the impossible, whatever remains, however improbable, must be the truth?” What was left was that the error message is erroneous and the problem had nothing to do the linked server configuration. This go me thinking about the views, which in turn sparked the question “Is the meta data being incorrect?”. A quick test on one of the views proved me correct.
There is an example in Books Online that shows you how to update dependent objects within a given database, this is not going to work for linked servers or update all views in every database.

so I set about creating a script to update the relevant views in every database that used the linked server:

EXEC sp_msforeachdb 'USE [?];
DECLARE @viewname sysname ;
DECLARE @cmd nvarchar(4000) ;
DECLARE view_cursor CURSOR
   FOR SELECT name FROM sys.views WHERE OBJECT_DEFINITION(object_id) LIKE ''%<Linked Server>%'' ;
OPEN view_cursor
FETCH NEXT FROM view_cursor INTO @viewname

WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd = ''EXEC sp_refreshview '''''' + @viewname + ''''''''
SELECT DB_NAME(), @cmd ;
EXEC ( @cmd ) ;
FETCH NEXT FROM view_cursor INTO @viewname
END

CLOSE view_cursor
DEALLOCATE view_cursor'


Change the name of the linked server if you want to use this script. As this wasn’t production code use the shortcut of sp_msforeachdb.

This solution happened to kill two birds, the reports actually started to run quicker!!

Filed under:
Chris Date in Edinburgh
05 February 12 11:48 AM | MartinBell | with no comments

Chris date is returning to the UK on June 7th and 8th.

Details of the course titled "Normal Forms and All That Jazz: A Database Professional's Guide to the Theory of Database Design" can be found at http://www.justsql.co.uk/chris_date/cjd_edin_may_2012.htm

This will appeal to everyone from Architects, DBAs and Developers and is based on his latest book due to be published soon.

Having attended one of Chris’ courses in the past, I know what a great teacher he is.

To register email: rde@justsql.com

Vital Statistics
21 January 12 10:06 PM | MartinBell | 1 comment(s)

I was asked the other day if there was any DMVs similar to the index fragmentation DMVs but for statistics. Unfortunately the answer is no! You can tell when a statistic was last by using DBCC SHOW_STATISTICS e.g.

DBCC SHOW_STATISTICS ( 'Sales.ContactCreditCard' , _WA_Sys_00000002_1A14E395 )

Which returns the updated date in the first set of results:

NameUpdatedRowsRows SampledStepsDensityAverage key lengthString IndexFilter ExpressionUnfiltered Rows
_WA_Sys_00000002_1A14E395Jan 15 2012  8:46PM1911819118414NO NULL19118


But this may get a little tiring if you have a few statistics that you need to check. It is easier to look at the sys.stats table and STATS_DATE function using a query similar to:

SELECT sc.name, o.name
, STATS_DATE(o.object_id,s.stats_id) AS [stats_date], s.*
FROM sys.stats s
JOIN sys.objects o ON o.object_id = s.object_id
JOIN sys.schemas sc ON sc.schema_id = o.schema_id

This will enable you to look at statistics for all tables or can be limited to look at one table using a where clause:

SELECT sc.name, o.name
, STATS_DATE(o.object_id,s.stats_id) AS [stats_date], s.*
FROM sys.stats s
JOIN sys.objects o ON o.object_id = s.object_id
JOIN sys.schemas sc ON sc.schema_id = o.schema_id
WHERE o.Name = ‘Contacts’

Using this you can tell how old the stats are but not necessarily how out of date they are. For instance if the data in the table is static, the statistics may never need to be updated.

So how can you tell if they may be out of date?

I mulled over the possibility of using the rowmodctr and rowcnt values in sysindexes to determine how many rows had changed compared to how many rows there is in the table. Looking at Books Online for sysindexes it says the following for rowmodctr
 

In earlier versions of SQL Server, the Database Engine maintained row-level modification counters. Such counters are now maintained at the column level. Therefore, the rowmodctr column is calculated and produces results that are similar to the results in earlier versions, but are not exact.

If you use the value in rowmodctr to determine when to update statistics, consider the following solutions:

  • Do nothing. The new rowmodctr value will frequently help you determine when to update statistics because the behavior is reasonably close to the results of earlier versions.
  • Use AUTO_UPDATE_STATISTICS. For more information see, Using Statistics to Improve Query Performance.
  • Use a time limit to determine when to update statistics. For example, every hour, every day, or every week.
  • Use application-level information to determine when to update statistics. For example, every time the maximum value of an identity column changes by more than 10,000, or every time a bulk insert operation is performed.

    If you use sp_updatestats to update the statistics, you can get the messages like:     
         
    Updating [Sales].[ContactCreditCard]
                [PK_ContactCreditCard_ContactID_CreditCardID], update is not necessary...
               [_WA_Sys_00000002_1A14E395], update is not necessary...
    0 index(es)/statistic(s) have been updated, 2 did not require update.

    when the statistics don’t need updating. So how does it determine this?

    The answer is that it only updates the statistics when rowmodctr is non-zero i.e. any changes to the data. it will also update statistics if the are not version current (I assume this when a database has been upgraded).     

    if ((@ind_rowmodctr <> 0)
         or ((@is_ver_current is not null)
                  and (@is_ver_current = 0
    )))
    begin
        
    --
        
    -- cut --
        
    --
    end
    else
    begin
        
    --raiserror('    %s, update is not necessary...', -1, -1, @ind_name_quoted)
         raiserror(15653, -1, -1, @ind_name_quoted
    )
         select @skipped_count = @skipped_count + 1
    end
       
    So it seems you may still need to develop your own solution to determine when statistics need updating if you need more control of when they are updated.

    Filed under:
    Powershell Snapins with SQL 2012
    08 December 11 07:23 PM | MartinBell | with no comments

    Because the only Adventureworks database on codeplex for SQL Server 2012 is a case sensitive database, I thought I would check my change-collation script to see what needed changing. I thought the only issue would be changing SqlServerCmdletSnapin100 to SqlServerCmdletSnapin110 but unfortunately that wasn’t the case Sad smile

    Running:

    Add-PSSnapin SqlServerCmdletSnapin110

    Gave the error message:

    Add-PSSnapin : No snap-ins have been registered for Windows PowerShell version 2.

    At line:1 char:13

    + Add-PSSnapin <<<< SqlServerCmdletSnapin110

    + CategoryInfo : InvalidArgument:

    (SqlServerCmdletSnapin110:String) [Add-PSSnapin], PSArgumentException

    + FullyQualifiedErrorId :

    AddPSSnapInRead,Microsoft.PowerShell.Commands.AddPSSnapinCommand

    So the snapin hadn’t been registered!  This can be confirmed when nothing is returned using the command:

    Add-PSSnapin –Registered SqlServerCmdletSnapin110

    So how do you register a snapin? Fortunately example 3 of the help for Add-PSSnapin lays it out for you. I found the dll in:

    C:\Program Files\Microsoft SQL Server\110\Tools\PowerShell\Modules\SQLPS\

    So the commands I used were:

    set-alias installutil

    $env:windir\Microsoft.NET\Framework\v2.0.50727\installutil.exe

    installutil "C:\Program Files\Microsoft SQL Server\110\Tools\PowerShell\Modules\SQLPS\Microsoft.SqlServer.Management.PSProvider.dll"

    installutil "C:\Program Files\Microsoft SQL Server\110\Tools\PowerShell\Modules\SQLPS\Microsoft.SqlServer.Management.PSSnapins.dll"

    get-PSSnapin -registered

    add-PSSnapin SQLServer*110

    This was great and I got the script running with only one other non SQL 2012 issue that needing fixing is was ready to go.

    I wondered why Microsoft had decided not to automatically register the DLL for you? My question was answered by Bob Beauchemin who explained the changes

    In SQL Server 2012 the PowerShell components for SQL Server are implemented as a module rather than as a snapin. To install it, just start (vanilla) PowerShell and enter "import-module sqlps" at the prompt (or put it in your profile.ps1) and ignore the warning about unapproved verbs. Or use"import-module sqlps -DisableNameChecking". That's the equivalent of what SQLPS 2012 does by default.

    Some of the docs look like they haven't yet been updated, but http://msdn.microsoft.com/en-us/library/cc281962(v=SQL.110).aspx describes the general concepts/changes. You'll also get the new SQLAS modules, and there's some new "subdirectories" for XEvent and SSIS. The sqlps module is in C:\Program Files (x86)\Microsoft SQL Server\110\Tools on a 64-bit install.”

    This explains why all my bingoogle searchs for combinations of “snapin” “SQL 2012” “denali” and “pssnapin” turned up nothing!

    You can read more about importing the sqlps module here
    .
    Loading the whole module seems to me a bit of an overkill if you only want the commandlets, but who am I to argue with the new order?

    I then decided that it would be a good idea to come up with something to put in my script which determine whether the system required the SQL 2008 snapins or the SQL 2012 module to be loaded. This is what I have come up with:

    if ( Get-PSSnapin -Registered | where {$_.name -eq 'SqlServerProviderSnapin100'} )
    {
        if( !(Get-PSSnapin | where {$_.name -eq 'SqlServerProviderSnapin100'}))
        { 
            Add-PSSnapin SqlServerProviderSnapin100 | Out-Null
        } ; 
        if( !(Get-PSSnapin | where {$_.name -eq 'SqlServerCmdletSnapin100'}))
        { 
            Add-PSSnapin SqlServerCmdletSnapin100 | Out-Null
        }
    }
    else
    {
        if( !(Get-Module | where {$_.name -eq 'sqlps'}))
        { 
            Import-Module 'sqlps' –DisableNameChecking
        }
    }

    It assumes SQL 2008 servers will have the SqlServerProviderSnapin100 and SqlServerCmdletSnapin100 registered otherwise it is a SQL 2012 system.

    My updated Change-Collation script can be found here

    SQLBits X–Registrations are open
    07 December 11 04:14 PM | MartinBell | with no comments

    Today we opened registrations for SQLBits X. Everyone registered on SQLBits.com should have received an email, but in case you aren’t here is the information:

    Dear Sir/Madam,
    We have two pieces of big news for you this week. In the words of organiser Tim Kent “It’s gonna be massive”

    Here at SQLBits we are so honoured and delighted to announce that Microsoft recognises SQLBits X as the official UK SQL Server 2012 Technical Launch Event.

    And, if that’s not enough…..then

    Registration for SQLBits X - The UK SQL Server 2012 Technical Launch Event, is officially open! We simply could not wait and decided to open up registration immediately.

    Phew!!!!

    Oh and also… we have received submissions from Microsoft’s Cathy Dumas, Elad Ziklik and Matt Masson. As well as MVPs; Denny Cherry, Adam Machanic and Stacia Misner. Not to mention the array of other Microsoft Certified Masters, Microsoft Most Valuable Professionals and Microsoft Staff who will be attending. In the meantime, check out the sessions that have already been submitted from both the best SQL Server speakers in the world and from new speakers.

    New to SQLBits, allow us to explain what you would expect at a SQLBits event.

    The conference will be taking place between the 29th and 31st of March 2012 at the Novotel London West. The event will be the biggest and best yet, we have capacity for 900 people and expect to sell out really quickly.

    The format for SQLBits X is the same as always with leading speakers from all around the world – with the added buzz of the UK SQL Server 2012 Technical Launch Event thrown in for good measure.

    Thursday will be a series of full day sessions delivered by renowned presenters followed by Fusion-io’s follow-up to last year’s highly entertaining Crappy Code Games in the evening.

    Friday is a day filled with regular sessions delivered by our highest rated speakers and Microsoft superstars and will feature an all new SQLBits Social event that should not be missed!

    As always we will conclude proceedings on the Saturday with our free Community Day.

    We want as many SQL Server professionals to take advantage of this unique event. To that end, for the fourth conference in a row, we are freezing the prices to attend.

    The prices for SQLBits X are as follows; register early to take advantage of our early bird discounts.

    All prices are exclusive of VAT. Prices are in UK Pounds Sterling (GBP). 

    Cut-Off Date
    midnight on the

    Pre-Conference
    Thursday

    Deep Dive
    Friday

    Full Conference
    Thursday & Friday

    Community Day
    Saturday

    Early Bird

    5th Jan 2012

    £250.00

    £125.00

    £375.00

    FREE

    Standard

    4th Mar 2012

    £300.00

    £175.00

    £475.00

    Last Minute

    £350.00

    £225.00

    £575.00

    Discounts are available from local user groups. Contact your user group organiser for details.

    Extra Discount - 20% off when 6 or more people book for the whole conference.

    We are also really excited to announce that the SQLBits website is now running on SQL Server 2012. There are some really exciting additions that we are hoping to bring you based on the new functionality in SQL Server 2012. Why not download SQL Server 2012 RC0 now to experience the new functionality for yourself.

    It is a testament to previous SQLBits attendees and sponsors that we have received this recognition. We hope we can thank all attendees, both new and old at the official UK SQL Server 2012 Technical Launch Event!

    Regards,

    SQLBits Committee

    Calling DTUtil recursively from Powershell
    01 December 11 10:47 PM | MartinBell | with no comments

    I’ve used DTUtil numerous times to load SSIS packages, but usually it is to load one or more packages to the same location. From the command prompt you can use a command such as

    FOR %i in (*.dtsx) DO DTUTIL –File “%i” –Decrypt SecretPassword –Destserver SQLServerInstance –Encrypt SQL; “%~ni”; 5

    If you are not familiar with DTUIL check out the
    documentation on MSDN.

    Using the above command is fine if you have all the packages in one directory and they all go to the same destination. If you have multiple directories containing files then you will need to repeat the command for each directory. With Powershell it is very easy to recurse through directories and process each file and there are many example available such as
    this one that will give you a quick start.

    The main issue using DTUtil is that if you try to copy a package to a folder that doesn’t exist DTUtil will automatically create the folder, therefore for each directory you need to check the existence of the destination folder. To do this I have used DTUTIL and the /FE flag, then checking the $LASTERROR variable tells me if it exists.

    The whole script can be found HERE. There are other ways of doing this, but combining this utility with Powershell gives you a quick solution to the problem.

    Filed under: ,
    Using Powershell to remove strings in files
    31 October 11 10:12 PM | MartinBell | 1 comment(s)

    I was on a SQL 2005 site the other day, which was using a batch scripts to create their databases from files in version control. The process works well (if not that quickly!), and you can easily tell if a scripts has worked by the fact that the output file has zero length. This means you can quickly sort the output files and concentrate on the scripts which have failed. Unfortunately it was not that simple on this system because of the high occurrence of the messages like:

    Cannot add rows to sys.sql_dependencies for the stored procedure because it depends on the missing table '<Some table>'. The stored procedure will still be created; however, it cannot be successfully executed until the table exists.

    So I decided to create a Powershell script to remove the occurrences of these strings in the output files. After a short while I ended up with this, which did the job (this may wrap!):

    $Files=get-Childitem "C:\temp\database"  "*.out"  -rec;
    foreach ($file in $Files) {
    (get-Content $file.PSPath ) | where { $_ -inotmatch "Cannot add rows to sys.sql_dependencies"  } | Add-Content -literalPath ( $file.PSPath -replace '\.out','.txt' ) ;
    remove-item -Force -Path $file.PSPath
    }

    I started off trying to replace the strings in the current file, but had issues with the file being already open. I then tried writing only lines that didn’t contain a given string and interim, and once processed I renamed this intermediate file. This was fine unless the file only contained lines that had the string in them, as they would be left alone, so I added the remove-item, and left the interim files.

    If you need to check for additional string you can use the add additional checks in the where object with the –and option e.g.

    $Files=get-Childitem "C:\temp\database" "*.out" -rec;
    foreach ($file in $Files) {
    (get-Content $file.PSPath ) | where { $_ -inotmatch "Cannot add rows to sys.sql_dependencies" -and $_ -inotmatch "The module will still be created; however, it cannot run successfully until the object exists." } | Add-Content -literalPath ( $file.PSPath -replace '\.out','.txt' ) ;
    remove-item -Force -Path $file.PSPath
    }
    Filed under:
    More Posts Next page »

    This Blog

    SQL Blogs

    Syndication