DECLARE @Database VARCHAR(255) DECLARE @Table VARCHAR(255) DECLARE @cmd NVARCHAR(500) DECLARE @fillfactor INT SET @fillfactor = 90 DECLARE DatabaseCursor CURSOR FOR SELECT name FROM master.dbo.sysdatabases WHERE name NOT IN ('master','msdb','tempdb','model','distribution') ORDER BY 1 OPEN DatabaseCursor FETCH NEXT FROM DatabaseCursor INTO @Database WHILE @@FETCH_STATUS = 0 BEGIN SET @cmd = 'DECLARE TableCursor CURSOR FOR SELECT ''['' + table_catalog + ''].['' + table_schema + ''].['' + table_name + '']'' as tableName FROM [' + @Database + '].INFORMATION_SCHEMA.TABLES WHERE table_type = ''BASE TABLE''' -- create table cursor EXEC (@cmd) OPEN TableCursor FETCH NEXT FROM TableCursor INTO @Table WHILE @@FETCH_STATUS = 0 BEGIN IF (@@MICROSOFTVERSION / POWER(2, 24) >= 9) BEGIN -- SQL 2005 or higher command SET @cmd = 'ALTER INDEX ALL ON ' + @Table + ' REBUILD WITH (FILLFACTOR = ' + CONVERT(VARCHAR(3),@fillfactor) + ')' EXEC (@cmd) END ELSE BEGIN -- SQL 2000 command DBCC DBREINDEX(@Table,' ',@fillfactor) END FETCH NEXT FROM TableCursor INTO @Table END CLOSE TableCursor DEALLOCATE TableCursor FETCH NEXT FROM DatabaseCursor INTO @Database END CLOSE DatabaseCursor DEALLOCATE DatabaseCursor
I was surprised to find out that overnight, a unique identifier had jumped from 6 to 1012 and upon investigation, it looks like SQL Server, when restarted, messes up the seed of the unique identifier to a new value (this is why you should never use ints for primary keys!)
Don’t expect identity values to be dense. For example, a rollback when inserting a row will cause an identity value to be “consumed” leaving a gap in the numbers.
I wrote a small SP which can be used to re-seeed the identity of a table in a all DBs on a server:
USE [master] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[ResetOrderIdentityAfterRestart] AS BEGIN begin TRAN SET NOCOUNT ON; DECLARE @db_name varchar(280), @SQL nvarchar(500); PRINT '-------- DB Reseet Report --------'; DECLARE db_name_cursor CURSOR FOR select DatabaseName + '.dbo.table' from tblClients WHERE ACTIVE = 1 OPEN db_name_cursor FETCH NEXT FROM db_name_cursor INTO @db_name WHILE @@FETCH_STATUS = 0 BEGIN PRINT ' ' print '----- Resetting count: ' + @db_name -- Declare an inner cursor based -- on vendor_id from the outer cursor. SET @SQL = ' declare @id int = 0 SELECT @id = MAX(ID) FROM ' + @db_name + ' DBCC CHECKIDENT (''' + @db_name + ''', reseed, @id) ' exec sp_executeSQL @SQL FETCH NEXT FROM db_name_cursor INTO @db_name END CLOSE db_name_cursor; DEALLOCATE db_name_cursor; Commit END
Then add it in to Start up by using following syntax.
EXEC sp_procoption 'ResetOrderIdentityAfterRestart', 'startup', 'on';
First, you will need to enable xp_cmdshell
-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1;
-- To update the currently configured value for advanced options.
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1;
-- To update the currently configured value for this feature.
Next, you will need to change the path to the directories:
USE Master; GO SET NOCOUNT ON -- 1 - Variable declaration DECLARE @backupPath NVARCHAR(500) DECLARE @cmd NVARCHAR(500) DECLARE @fileList TABLE (backupFile NVARCHAR(255)) -- 2 - Initialize variables SET @backupPath = 'F:\baks\' -- 3 - get list of files SET @cmd = 'DIR /b "' + @backupPath + '"' INSERT INTO @fileList(backupFile) EXEC master.sys.xp_cmdshell @cmd SELECT 'RESTORE DATABASE [' + LEFT(backupFile, CHARINDEX('_', backupFile, 12)-1) + '] FROM DISK = ''' + @backupPath + backupFile + ''' WITH RECOVERY, REPLACE GO' from @fileList
Copy the generated script into a new window and voila! Your script is done. Just press F5 to run it.
Don’t forget to turn off xp_cmdshell when done.
There are occasions where you would like to search in a varchar column and order the results based on the numeric part of the field.
Imagine the following table:
ABC ABC1 ABC2 ABC3 and so on... ABC11 ABC12 ABC13 and so on.. ABC20 ABC21 ABC22 and so on..
So basically what I have is any string value (not always ABC, any string value) that can either be followed by the number or it may just be a string without the number.
When you run
select * from table order by my column asc
you get following results:
ABC ABC1 ABC11 ABC12 ABC13 ABC2 ABC20 ABC21 ABC22 ABC3 ABC31 ABC32
In this scenario, you would need the results sorted by the numeric value and not alphabetically.
ABC ABC1 ABC2 ABC3 ABC11 ABC12 ABC13 ABC20 ABC21 ABC22 ABC31 ABC32
How can this be accomplished?
In some cases, to improve performance, you might choose to re-compile all database objects and while you can use DBCC FREEPROCCACHE to clear the cache and force re-compilation, you can also use the following function to trigger a global re-compile.
This is especially useful if you are struggling to copy databases and old code error does not let you skip steps. Continue reading “Script to recompile all stored procedures – T-SQL”
When you are manipulating large quantities of data, you might have some records containing email addresses which slip through as invalid.
Following function checks these conditions:
No embedded spaces
‘@’ can’t be the first character of an email address
‘.’ can’t be the last character of an email address
There must be a ‘.’ somewhere after ‘@’
the ‘@’ sign is allowed
Domain name should end with at least 2 character extension
can’t have patterns like ‘.@’ and ‘..’
--print dbo.fnc_isValidEmail('Mi firstname.lastname@example.org')
CREATE FUNCTION fnc_IsValidEmail
DECLARE @Valid bit
SET @Valid = 0
SET @Valid = 1
CHARINDEX(' ',LTRIM(RTRIM(@email_address))) = 0
AND LEFT(LTRIM(@email_address),1) <> '@'
AND RIGHT(RTRIM(@email_address),1) <> '.'
AND CHARINDEX('.',@email_address ,CHARINDEX('@',@email_address)) - CHARINDEX('@',@email_address ) > 1
AND LEN(LTRIM(RTRIM(@email_address ))) - LEN(REPLACE(LTRIM(RTRIM(@email_address)),'@','')) = 1
AND CHARINDEX('.',REVERSE(LTRIM(RTRIM(@email_address)))) >= 3
AND (CHARINDEX('.@',@email_address ) = 0 AND CHARINDEX('..',@email_address ) = 0)
SET @Valid = 1
How to call:
SELECT Email, dbo.fnc_IsValidEmail(Email) as Valid
If you have been using this:
SUBSTRING(str_col, PATINDEX('%[^0]%', str_col), LEN(str_col))
to get your zeroes removed from a string, you might be interested in a variation that only removes the leading zeroes. The T-SQL Function has been created to be called from either Stored Procedure code or Triggers.
--print dbo.ufn_TrimLeadingZeros ('0100 ATN652') ALTER FUNCTION [dbo].[ufn_TrimLeadingZeros] ( @Input VARCHAR(50) ) RETURNS VARCHAR(50) AS BEGIN --RETURN REPLACE(LTRIM(REPLACE(@Input, '0', ' ')), ' ', '0') RETURN SUBSTRING(@Input, PATINDEX('%[^0]%', @Input+'.'), LEN(@Input)) END