About This Blog

.net & SQL Samples, programming tips and tricks, performance tips, guidelines, and best practices

Monday, 11 March 2013

SQL Server – Generating PERMUTATIONS using T-Sql

Were you ever asked to generate string Permutations using TSql? I was recently asked to do so, and the logic which I could manage to come up at that point is shared in the below script.

DECLARE @Value AS VARCHAR(20) = 'ABCC' --Mention the text which is to be permuted
DECLARE @NoOfChars AS INT = LEN(@Value)
DECLARE @Permutations TABLE(Value VARCHAR(20)) --Make sure the size of this Value is equal to your input  string length (@Value)
 
;WITH NumTally AS (--Prepare the Tally Table to separate each character of the Value.
  SELECT 1 Num
  UNION ALL
  SELECT 
    Num + 1 
  FROM 
    NumTally 
  WHERE 
    Num < @NoOfChars
),Chars AS ( --Separate the Characters
SELECT
  Num,
  SUBSTRING(@Value,Num,1) Chr
FROM
  NumTally  
)
 
--Persist the Separated characters.
INSERT INTO @Permutations
SELECT Chr FROM Chars
 
--Prepare Permutations
DECLARE @i AS INT = 1
WHILE(@i < @NoOfChars)
BEGIN
 
  --Store the Permutations
  INSERT INTO @Permutations
  SELECT DISTINCT --Add DISTINCT if required else duplicate Permutations will be generated for Repeated  Chars.
    P1.Value + P2.Value
  FROM 
    (SELECT Value FROM @Permutations WHERE LEN(Value) = @i) P1 
  CROSS JOIN 
    (SELECT Value FROM @Permutations WHERE LEN(Value) = 1) P2
  
  --Increment the Counter.      
  SET @i += 1  
  
  --Delete the Incorrect Lengthed Permutations to keep the table size under control.
  DELETE FROM @Permutations WHERE LEN(Value) NOT IN (1,@i)
END
 
--Delete InCorrect Permutations.
SET @i = 1
WHILE(@i <= @NoOfChars)
BEGIN
 
  --Deleting Permutations which has not used "All the Chars of the given Value".
  DELETE 
  FROM 
    @Permutations
  WHERE
    Value NOT LIKE '%' + SUBSTRING(@Value,@i,1) +'%'
  
  --Deleting Permutations which have repeated incorrect character.  
  DELETE 
  FROM 
    @Permutations
  WHERE
    LEN(Value) - LEN(REPLACE(Value,SUBSTRING(@Value,@i,1),'')) != 
    LEN(@Value) - LEN(REPLACE(@Value,SUBSTRING(@Value,@i,1),''))
    
  SET @i += 1  
END
 
--Selecting the generated Permutations. 
SELECT Value FROM @Permutations

Hope, this script helps!


Please share your suggestions if you have any to improve this logic.

Wednesday, 6 March 2013

SQL Server – TSql to find Records matching certain criteria in all the tables of a DB.

Generally, we try to find out records matching a certain criteria from a single or few tables. However, there are times when we need to find out records matching a criteria from all the tables of a SQL Database and today I will explain you a simple way to retrieve those records.

Recently, I was asked by my colleague, who was working on a MS Dynamics CRM migration project, to let him know the records which were created after a particular date in the source. So that, he could analyze only those records and strategize the Migration process.

I quickly opened up the SSMS and came up with the below script -

USE <DBName> --Replace this with the actual DBName
Go
 
DECLARE @ColumnName AS VARCHAR(50) = 'CreatedOn' --The name of the column on which you need to put the criteria
DECLARE @Criteria AS VARCHAR(50) = 'CONVERT(DATE,' + @ColumnName + ') >= ''20130225''' -- The Actual criteria/WHERE Clause of the query
 
--The below will list the TSQL Statements which could be copied & executed in a separate query window.
SELECT 
  'IF EXISTS(SELECT 1 FROM ' + T.name + ' WHERE ' + @Criteria + ') ' +
  'SELECT ''' + T.name + ''' TableName, * FROM ' + T.name + ' WHERE ' + @Criteria 
FROM 
  sys.columns C
INNER JOIN sys.tables T
  ON T.object_id = C.object_id   
WHERE 
  C.name = @ColumnName


The above script will list down the SELECT statements which could be copied and executed in a separate query window connecting to the same Database. On execution, you will get the list of records from each table base on the specified criteria.


Hope, this helps!

Monday, 14 January 2013

TFS – Workspace Mapping issues for Different Users

I have been using TFS 2010 from quite sometime now and have found it really cool! However, the management of workspaces can be a bit tricky at times.

In real scenario, many times we come across a situation when some user has to work on someone else machine and on the same project; e.g. old team member leaves the project & a new one replaces him and is allotted the same machine, a team member might leave the company, etc. 

So, the need arises to create a new workspace & map it to the same physical folder tree to avoid replication of the files at different location. (Please note : This step can be avoided if the existing workspace was a Public Workspace). While mapping the workspace to the same folder which is already mapped to the workspace of some other user, we get a message - “The working folder {PATH} is already in use by the workspace MachineName;Username on computer MachineName.” and this is by design - that we can not map the same working folder to multiple workspaces, in order to maintain the state consistency.
Now, what is the solution to this issue. The solutions are -
  1. Remove the existing mapping.
  2. Or Delete the existing Workspace.
Workspaces can be removed using some command line TFS commands. However, there are situations when we even can not remove the workspaces; reason being, the owning domain user of the workspace to be removed - “DOES NOT EXIST” and as a workaround to this, I have written a simple SQL script, which could be executed on the TFS Database of our Project to remove the mappings.
Please note that this is not a “Supported Way”. I am sharing this just because it has worked for me and might save some of your time too. Also, please take appropriate DB backup before executing the script and if possible execute it under any DBA’s guidance. So, here is the time saver script… :)
DECLARE @WorkspaceID AS INT
DECLARE @WorkspaceName AS NVARCHAR(64)
 
--Set the Name of the Workspace whose mappings are to be removed.
SET @WorkspaceName = '{NameOfWorkspace}'
 
--Get the WorkspaceID of the Workspace to be removed.
SELECT
  @WorkspaceID = W.WorkspaceId
FROM
  dbo.tbl_Workspace W
WHERE
  W.WorkspaceName = @WorkspaceName
  
--Delete the details of working folder for this workspace.
DELETE
FROM
  dbo.tbl_WorkingFolder
WHERE
  WorkspaceID = @WorkspaceID
 
 
--Delete the mapping details for this workspace.
DELETE
FROM
  dbo.tbl_WorkspaceMapping
WHERE
  WorkspaceID = @WorkspaceID

Hope, this helps you. Also, please revert if you have some other workarounds too.

Monday, 26 November 2012

SSRS # How to achieve Dynamic Sorting in SSRS?

Introduction
I wrote a blog on “Dynamic Sorting” in SSRS sometime back. Even though I successfully achieved sorting the data dynamically, I failed to find out a way of applying the “Sort Direction” dynamically as the Sort Direction did not accept an expression to manage it.
Recently, I came across a trick which solves this very easily purely in SSRS. Let’s jump on to the implementation now without wasting much time.

Implementation
Continuing with the same example of sorting 3 columns – Col1,Col2 & Col3 in any preferred order, we can specify the Sort Direction dynamically in the following way -
1. Define 3 additional parameters - @Col1SortDirection,@Col2SortDirection & @Col3SortDirection of STRING type.

2. While setting the Sort Options for Tablix or Group, we have to define sorting for double the number the sorting columns as under -

Sort Direction












The Sort By expressions will be defined as under -
a. IIF(Parameters!Col1SortDirection.Value = "Ascending",Fields(Parameters!SortCol1Name.Value).Value,Nothing)
b. IIF(Parameters!Col1SortDirection.Value = "Descending",Fields(Parameters!SortCol1Name.Value).Value,Nothing)
c. IIF(Parameters!Col2SortDirection.Value = "Ascending",Fields(Parameters!SortCol2Name.Value).Value,Nothing)
d. IIF(Parameters!Col2SortDirection.Value = "Descending",Fields(Parameters!SortCol2Name.Value).Value,Nothing)
e. IIF(Parameters!Col3SortDirection.Value = "Ascending",Fields(Parameters!SortCol3Name.Value).Value,Nothing)
f. IIF(Parameters!Col3SortDirection.Value = "Descending",Fields(Parameters!SortCol3Name.Value).Value,Nothing)

Note: we can use any CONSTANT value to replace Nothing used in above expression.

3. Pass the required Sort Direction, say - @Col1SortDirection = “Ascending”, @Col2SortDirection = “Descending” & @Col3SortDirection = “Ascending” or in any preferred value.

4. Pass the values for other parameters as explained in my last post.

Conclusion
With this we can now easily control the dynamic sorting with full flexibility of specifying the Column Names & the Sort Direction both dynamically using pure SSRS.
Hope, this will help you a lot!

Wednesday, 17 October 2012

SQL Server # Database Backup Report using T-SQL

Today, I am going to share few very useful scripts which will report us on Database Backup from different view points.

To get the List/History/Log of all the Successful Backups

SELECT 
  b.machine_name,
  b.server_name,
  b.database_name as DBName,
  b.backup_start_date,
  b.backup_finish_date,
  CASE 
    WHEN b.[type] = 'D' THEN 'Database'
    WHEN b.[type] = 'I' THEN 'Differential database'
    WHEN b.[type] = 'L' THEN 'Log'
    WHEN b.[type] = 'F' THEN 'File or filegroup'
    WHEN b.[type] = 'G' THEN 'Differential file'
    WHEN b.[type] = 'P' THEN 'Partial'
    WHEN b.[type] = 'Q' THEN 'Differential partial'
    ELSE b.[type]
  END Backup_Type,    
  b.expiration_date,
  b.[user_name],
  DATEDIFF(MINUTE,b.backup_start_date ,b.backup_finish_date) as Total_Time_in_Minute,
  b.recovery_model,
  b.backup_size/(1024 * 1024 * 1024) as Total_Size_GB,
  bf.physical_device_name as Location
FROM 
  msdb.dbo.backupset AS b
INNER JOIN msdb.dbo.backupmediafamily AS bf
  ON b.media_set_id=bf.media_set_id
ORDER BY 
  b.backup_start_date DESC
GO


To get a list of all successful Backups taken till date for a particular Database



DECLARE @DBName AS VARCHAR(100) = 'Your Database Name'
 
SELECT 
  b.machine_name,
  b.server_name,
  b.database_name as DBName,
  b.backup_start_date,
  b.backup_finish_date,
  CASE 
    WHEN b.[type] = 'D' THEN 'Database'
    WHEN b.[type] = 'I' THEN 'Differential database'
    WHEN b.[type] = 'L' THEN 'Log'
    WHEN b.[type] = 'F' THEN 'File or filegroup'
    WHEN b.[type] = 'G' THEN 'Differential file'
    WHEN b.[type] = 'P' THEN 'Partial'
    WHEN b.[type] = 'Q' THEN 'Differential partial'
    ELSE b.[type]
  END Backup_Type,
  b.expiration_date,
  b.[user_name],
  DATEDIFF(MINUTE,b.backup_start_date ,b.backup_finish_date) as Total_Time_in_Minute,
  b.recovery_model,
  b.backup_size/(1024 * 1024 * 1024) as Total_Size_GB,
  bf.physical_device_name as Location
FROM 
  msdb.dbo.backupset AS b
INNER JOIN msdb.dbo.backupmediafamily AS bf
  ON b.media_set_id=bf.media_set_id
WHERE
  b.database_name = @DBName  
ORDER BY 
  b.backup_start_date DESC
GO

To get the List of all Databases which are not backed up till date



SELECT
  d.name [DB_Name]
FROM
  master.sys.databases d
LEFT JOIN msdb.dbo.backupset b
  ON b.database_name = d.name
WHERE
  d.database_id IS NULL


To get the List of all Databases which are not backed up since last X days



DECLARE @LastXDays AS INT = 1
;WITH LatestBackupSet AS (
SELECT 
  b.database_name as DBName,
  b.backup_start_date LastBackedUpOn,
  b.[user_name],
  ROW_NUMBER() OVER(PARTITION BY b.database_name ORDER BY b.backup_start_date DESC) Rnk
FROM 
  msdb.dbo.backupset AS b
)
SELECT 
  lbs.DBName,
  lbs.LastBackedUpOn,
  lbs.[user_name]
FROM 
  LatestBackupSet AS lbs
WHERE
  DATEDIFF(DAY,lbs.LastBackedUpOn ,CURRENT_TIMESTAMP) = @LastXDays  
  AND lbs.Rnk = 1
ORDER BY 
  lbs.DBName DESC
GO


To get a list of the Latest successful backups of all Databases



;WITH LatestBackupSet AS (
SELECT 
  b.machine_name,
  b.server_name,
  b.database_name as DBName,
  b.backup_start_date,
  b.backup_finish_date,
  CASE 
    WHEN b.[type] = 'D' THEN 'Database'
    WHEN b.[type] = 'I' THEN 'Differential database'
    WHEN b.[type] = 'L' THEN 'Log'
    WHEN b.[type] = 'F' THEN 'File or filegroup'
    WHEN b.[type] = 'G' THEN 'Differential file'
    WHEN b.[type] = 'P' THEN 'Partial'
    WHEN b.[type] = 'Q' THEN 'Differential partial'
    ELSE b.[type]
  END Backup_Type,
  b.expiration_date,
  b.[user_name],
  DATEDIFF(MINUTE,b.backup_start_date ,b.backup_finish_date) as Total_Time_in_Minute,
  b.recovery_model,
  b.backup_size/(1024 * 1024 * 1024) as Total_Size_GB,
  bf.physical_device_name as Location,
  ROW_NUMBER() OVER(PARTITION BY b.database_name ORDER BY b.backup_start_date DESC) Rnk
FROM 
  msdb.dbo.backupset AS b
INNER JOIN msdb.dbo.backupmediafamily AS bf
  ON b.media_set_id=bf.media_set_id
)
SELECT 
  machine_name,
  server_name,
  DBName,
  backup_start_date,
  backup_finish_date,
  Backup_Type,
  expiration_date,
  [user_name],
  Total_Time_in_Minute,
  recovery_model,
  Total_Size_GB,
  Location
FROM 
  LatestBackupSet AS lbs
WHERE
  lbs.Rnk = 1
ORDER BY 
  lbs.DBName DESC
GO


To get the Latest successful backup of a particular Database



DECLARE @DBName AS VARCHAR(100) = 'Your Database Name'
 
;WITH LatestBackupSet AS (
SELECT 
  b.machine_name,
  b.server_name,
  b.database_name as DBName,
  b.backup_start_date,
  b.backup_finish_date,
  CASE 
    WHEN b.[type] = 'D' THEN 'Database'
    WHEN b.[type] = 'I' THEN 'Differential database'
    WHEN b.[type] = 'L' THEN 'Log'
    WHEN b.[type] = 'F' THEN 'File or filegroup'
    WHEN b.[type] = 'G' THEN 'Differential file'
    WHEN b.[type] = 'P' THEN 'Partial'
    WHEN b.[type] = 'Q' THEN 'Differential partial'
    ELSE b.[type]
  END Backup_Type,
  b.expiration_date,
  b.[user_name],
  DATEDIFF(MINUTE,b.backup_start_date ,b.backup_finish_date) as Total_Time_in_Minute,
  b.recovery_model,
  b.backup_size/(1024 * 1024 * 1024) as Total_Size_GB,
  bf.physical_device_name as Location,
  ROW_NUMBER() OVER(PARTITION BY b.database_name ORDER BY b.backup_start_date DESC) Rnk
FROM 
  msdb.dbo.backupset AS b
INNER JOIN msdb.dbo.backupmediafamily AS bf
  ON b.media_set_id=bf.media_set_id
WHERE
  b.database_name = @DBName  
)
SELECT 
  machine_name,
  server_name,
  DBName,
  backup_start_date,
  backup_finish_date,
  Backup_Type,
  expiration_date,
  [user_name],
  Total_Time_in_Minute,
  recovery_model,
  Total_Size_GB,
  Location
FROM 
  LatestBackupSet AS lbs
WHERE
  lbs.Rnk = 1
ORDER BY 
  lbs.DBName DESC
GO


To get a list of Databases that were backed-up and do not currently exist



SELECT
  DISTINCT b.database_name
FROM
  msdb.dbo.backupset b
WHERE
  DB_ID(b.database_name) IS NULL

Hope, the above given script will be of help to you. Also, I would like to request you to please add any relevant script which you feel would be useful as a comment.