How to Script Login and User Permissions in SQL Server

How to Script Login and User Permissions in SQL Server

How to Script Login and User Permissions in SQL Server

Migrating login and user permissions to a new instance is one of the most common tasks for a SQL DBA. This post “How to Script Login and User Permissions in SQL Server“ can help you in scripting the login and the user permissions for a given database. Most of us knew that there is a script “sp_help_revlogin” available for migrating SQL Server logins which can also handle the passwords for SQL Server logins. Just to summarize the topic we are also giving the MS suggested script.

Server / Instance Level

  • Script Logins with Passwords
  • Script Login Server Roles
  • Script the Server Level Permissions

Database / Object Level

  • Script User Creation
  • Script User Database Roles
  • Script the Database Level Permissions
  • Script Object Level Permission

 

Here is the script for generating Login creation script for the given SQL Server instance. Here is the reference from the MS site. https://support.microsoft.com/en-us/help/918992/how-to-transfer-logins-and-passwords-between-instances-of-sql-server

There is another beautiful script provided by JP Chen and it also working for login migration.

Server / Instance Level:

--https://www.datavail.com/blog/scripting-out-the-logins-server-role-assignments-and-server-permissions/
/********************************************************************************************************************/
-- Scripting Out the Logins, Server Role Assignments, and Server Permissions
/********************************************************************************************************************/
SET NOCOUNT ON
-- Scripting Out the Logins To Be Created
SELECT 'IF (SUSER_ID('+QUOTENAME(SP.name,'''')+') IS NULL) BEGIN CREATE LOGIN ' +QUOTENAME(SP.name)+
			   CASE 
					WHEN SP.type_desc = 'SQL_LOGIN' THEN ' WITH PASSWORD = ' +CONVERT(NVARCHAR(MAX),SL.password_hash,1)+ ' HASHED, CHECK_EXPIRATION = ' 
						+ CASE WHEN SL.is_expiration_checked = 1 THEN 'ON' ELSE 'OFF' END +', CHECK_POLICY = ' +CASE WHEN SL.is_policy_checked = 1 THEN 'ON,' ELSE 'OFF,' END
					ELSE ' FROM WINDOWS WITH'
				END 
	   +' DEFAULT_DATABASE=[' +SP.default_database_name+ '], DEFAULT_LANGUAGE=[' +SP.default_language_name+ '] END;' COLLATE SQL_Latin1_General_CP1_CI_AS AS [-- Logins To Be Created --]
FROM sys.server_principals AS SP LEFT JOIN sys.sql_logins AS SL
		ON SP.principal_id = SL.principal_id
WHERE SP.type IN ('S','G','U')
		AND SP.name NOT LIKE '##%##'
		AND SP.name NOT LIKE 'NT AUTHORITY%'
		AND SP.name NOT LIKE 'NT SERVICE%'
		AND SP.name <> ('sa');

-- Scripting Out the Role Membership to Be Added
SELECT 
'EXEC master..sp_addsrvrolemember @loginame = N''' + SL.name + ''', @rolename = N''' + SR.name + '''
' AS [-- Server Roles the Logins Need to be Added --]
FROM master.sys.server_role_members SRM
	JOIN master.sys.server_principals SR ON SR.principal_id = SRM.role_principal_id
	JOIN master.sys.server_principals SL ON SL.principal_id = SRM.member_principal_id
WHERE SL.type IN ('S','G','U')
		AND SL.name NOT LIKE '##%##'
		AND SL.name NOT LIKE 'NT AUTHORITY%'
		AND SL.name NOT LIKE 'NT SERVICE%'
		AND SL.name <> ('sa');


-- Scripting out the Permissions to Be Granted
SELECT 
	CASE WHEN SrvPerm.state_desc <> 'GRANT_WITH_GRANT_OPTION' 
		THEN SrvPerm.state_desc 
		ELSE 'GRANT' 
	END
    + ' ' + SrvPerm.permission_name + ' TO [' + SP.name + ']' + 
	CASE WHEN SrvPerm.state_desc <> 'GRANT_WITH_GRANT_OPTION' 
		THEN '' 
		ELSE ' WITH GRANT OPTION' 
	END collate database_default AS [-- Server Level Permissions to Be Granted --] 
FROM sys.server_permissions AS SrvPerm 
	JOIN sys.server_principals AS SP ON SrvPerm.grantee_principal_id = SP.principal_id 
WHERE   SP.type IN ( 'S', 'U', 'G' ) 
		AND SP.name NOT LIKE '##%##'
		AND SP.name NOT LIKE 'NT AUTHORITY%'
		AND SP.name NOT LIKE 'NT SERVICE%'
		AND SP.name <> ('sa');

SET NOCOUNT OFF

 

Database / Object Level:

USE Master  -- Use the required database name here
GO
SET NOCOUNT ON;

PRINT 'USE ['+DB_NAME()+']';
PRINT 'GO'

/********************************************************************************/
/**************** Create a new user and map it with login ***********************/
/********************************************************************************/

PRINT '/*************************************************************/'
PRINT '/************** Create User Script ***************************/'
PRINT '/*************************************************************/'

SELECT 'CREATE USER [' + NAME + '] FOR LOGIN [' + NAME + ']' 
FROM sys.database_principals
WHERE	[Type] IN ('U','S')
		AND 
		[NAME] NOT IN ('dbo','guest','sys','INFORMATION_SCHEMA')

GO
-- Troubleshooting User creation issues
PRINT '/***'+CHAR(10)+
'--Error 15023: User or role <XXXX> is already exists in the database.'+CHAR(10)+
'--Then Execute the below code can fix the issue'+CHAR(10)+
'EXEC sp_change_users_login ''Auto_Fix'',''<Failed User>'''+CHAR(10)+
'GO **/'

/************************************************************************/
/************  Script the User Role Information *************************/
/************************************************************************/

PRINT '/**********************************************************/'
PRINT '/************** Create User-Role Script *******************/'
PRINT '/**********************************************************/'

SELECT 'EXEC sp_AddRoleMember ''' + DBRole.NAME + ''', ''' + DBP.NAME + '''' 
FROM sys.database_principals DBP
INNER JOIN sys.database_role_members DBM ON DBM.member_principal_id = DBP.principal_id
INNER JOIN sys.database_principals DBRole ON DBRole.principal_id = DBM.role_principal_id
WHERE DBP.NAME <> 'dbo'

GO

/***************************************************************************/
/************  Script Database Level Permission ****************************/
/***************************************************************************/

PRINT '/*************************************************************/'
PRINT '/************** Database Level Permission ********************/'
PRINT '/*************************************************************/'

SELECT	CASE WHEN DBP.state <> 'W' THEN DBP.state_desc ELSE 'GRANT' END
		+ SPACE(1) + DBP.permission_name + SPACE(1)
		+ SPACE(1) + 'TO' + SPACE(1) + QUOTENAME(USR.name) COLLATE database_default
		+ CASE WHEN DBP.state <> 'W' THEN SPACE(0) ELSE SPACE(1) + 'WITH GRANT OPTION' END + ';' 
FROM	sys.database_permissions AS DBP
		INNER JOIN	sys.database_principals AS USR	ON DBP.grantee_principal_id = USR.principal_id
WHERE	DBP.major_id = 0 and USR.name <> 'dbo'
ORDER BY DBP.permission_name ASC, DBP.state_desc ASC


/***************************************************************************/
/************  Script Object Level Permission ******************************/
/***************************************************************************/

PRINT '/*************************************************************/'
PRINT '/************** Object Level Permission **********************/'
PRINT '/*************************************************************/'

SELECT	CASE WHEN DBP.state <> 'W' THEN DBP.state_desc ELSE 'GRANT' END
		+ SPACE(1) + DBP.permission_name + SPACE(1) + 'ON ' + QUOTENAME(USER_NAME(OBJ.schema_id)) + '.' + QUOTENAME(OBJ.name) 
		+ CASE WHEN CL.column_id IS NULL THEN SPACE(0) ELSE '(' + QUOTENAME(CL.name) + ')' END
		+ SPACE(1) + 'TO' + SPACE(1) + QUOTENAME(USR.name) COLLATE database_default
		+ CASE WHEN DBP.state <> 'W' THEN SPACE(0) ELSE SPACE(1) + 'WITH GRANT OPTION' END + ';' 
FROM	sys.database_permissions AS DBP
		INNER JOIN	sys.objects AS OBJ	ON DBP.major_id = OBJ.[object_id]
		INNER JOIN	sys.database_principals AS USR	ON DBP.grantee_principal_id = USR.principal_id
		LEFT JOIN	sys.columns AS CL	ON CL.column_id = DBP.minor_id AND CL.[object_id] = DBP.major_id
ORDER BY DBP.permission_name ASC, DBP.state_desc ASC



SET NOCOUNT OFF;

 

Summary:

The post “How to Script Login and User Permissions in SQL Server” can help you in transferring logins and users between SQL Server instances. Please do comment on the below comment box if you find any issues in code.

Download Scripts:

How to Script Login and User Permissions in SQL Server_Logins

How to Script Login and User Permissions in SQL Server_Users

Posted in SQL Scripts, SQL Server DBA | Tagged , , , , , , , , , , | 46 Comments

Get the Next and Previous Row Value in SQL Server

Get the Next and Previous Row Value in SQL Server

Get the Next and Previous Row Value in SQL Server

This post can help you to get the next and previous row Value in SQL Server using T-SQL. We had a requirement to get the previous row information and compare it with the current row value. Usually we do not suggest performing these operations at database side rather it can be done from application side as it easier the process in navigating row values. But in some cases we have to do it from back-end. Here is an example to get the next and previous row value in SQL Server using T-SQL script.

/**************************************************************/
/*** To Find the Next and Previous Row Value in SQL Server  ***/
/*** Works On: SQL Server 2012, 2014, 2016 ********************/
/**************************************************************/

-- Create a Dummy Table and Insert data
CREATE TABLE ScoreCard(
		ID		INT IDENTITY, 
		Name		VARCHAR(50) NOT NULL,
		Score		INT NOT NULL,
		ScoredOn	SMALLDATETIME NOT NULL);	 
GO
INSERT INTO ScoreCard (Name,Score,ScoredOn)
VALUES 
	('A',80,'2017-01-20'), 
	('A',50,'2017-01-22'),
	('A',65,'2017-01-23'),
	('A',92,'2017-01-25'),
	('A',100,'2017-01-30');

-- Report Requirement 
-- Below is the Expected output
-- Name, ScoredOn, PreviousScore, CurrentScore, NextScore

/*************************/
/*** 2012, 2014, 2016 ****/
/*************************/

SELECT	Name,
	CONVERT(VARCHAR(10),ScoredOn,103) 	AS 'ScoredOn', 
	LAG(s.Score) OVER (ORDER BY s.ID) 	AS 'PreviousScore',
	Score 					AS 'CurrentScore',
	LEAD(s.Score) OVER (ORDER BY s.ID)	AS 'NextScore'
FROM	dbo.ScoreCard s


-- When LEAD and LAG is not available i.e Before 2012
/*************************/
/*** Before 2012 *********/
/*************************/

;WITH SCCTE AS (
	SELECT	s.Name,
		CONVERT(VARCHAR(10),s.ScoredOn,103) AS 'ScoredOn',
		s.Score,
		ROW_NUMBER() OVER (ORDER BY s.ID) AS rownum
	FROM	dbo.ScoreCard s
)
SELECT	SCCTE.Name,
	SCCTE.ScoredOn,
	p.Score		AS 'PreviousScore',
	SCCTE.Score     AS 'CurrentScore',
	n.Score		AS 'NextScore'
FROM	SCCTE
LEFT JOIN SCCTE p ON p.rownum = SCCTE.rownum - 1 -- To get Previous row info
LEFT JOIN SCCTE n ON n.rownum = SCCTE.rownum + 1 -- To Get next row info
GO

-- Drop the dummy table
DROP TABLE ScoreCard;

Download the script file: Get the Next and Previous Row Value in SQL Server

Posted in Interview Q&A, SQL Development, SQL Scripts | Tagged , , , , , , , , , , | 2 Comments

SQL Server Date and Time related Interview Questions

SQL Server Date and Time related Interview Questions

SQL Server Date and Time related Interview Questions

This post can help you in answering SQL Server Date and Time related Interview Questions.  Below is the list of queries which are recently asked in SQL Server Developer interviews. These are not just for interview preparation also helps you as a quick reference while working on date & time related queries.

Along with these it would be good if you can refer the most commonly used DATETIME data types (DATE, TIME, SMALLDATETIME, DATETIME, DATETIME2, and DATETIMEOFFSET) and functions (GETDATE, SYSDATETIME, CONVERT, DATENAME, DATEPART, DATEDIFF, DATEADD, EOMONTH etc.)

/**********************************************************************/
/*************** SQL Server Date and Time Queries *********************/
/**********************************************************************/

------------------------- Date ------------------------

-- Retireve Current Date and Time
SELECT GETDATE() 'Today'

-- Retrieve Yesterday Date
SELECT DATEADD(d,-1,GETDATE()) 'Yesterday'

------------------------- Week ------------------------

-- Get the First Day of Current Week
SELECT DATEADD(wk,DATEDIFF(wk,0,GETDATE()),0) AS 'Current_Week_First_Day'

-- Get the Last Day of Current Week
SELECT DATEADD(wk,DATEDIFF(wk,0,GETDATE()),6) AS 'Current_Week_Last_Day';

-- Get the First Day of Last Week
SELECT DATEADD(wk,DATEDIFF(wk,7,GETDATE()),0) AS 'Last_Week_First_Day';

-- Get the Last Day of Last Week
SELECT DATEADD(wk,DATEDIFF(wk,7,GETDATE()),6) AS 'Last_Week_Last_Day';

------------------------- Month ------------------------

-- Get the First Day of Current Month
SELECT DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0) AS 'Current_Month_First_Day';

-- Get the Last Day of Current Month
SELECT DATEADD(ms,- 3,DATEADD(mm,0,DATEADD(mm,DATEDIFF(mm,0,GETDATE())+1,0))) AS 'Current_Month_Last_Day';

-- Get the First Day of Last Month
SELECT DATEADD(mm,-1,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0)) AS 'Last_Month_First_Day'

-- Get the Last Day of Last Month
SELECT DATEADD(ms,-3,DATEADD(mm,0,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))) AS 'Last_Month_Last_Day'

------------------------- Quarter ------------------------

-- Get the First Day of Current Quarter
SELECT Dateadd(qq, Datediff(qq,0,GetDate()), 0) AS 'Current_Quarter_First_Day'

-- Get the Last Day of Current Quarter
SELECT Dateadd(ms,-3,Dateadd(qq, Datediff(qq,0,GetDate())+1, 0)) AS 'Current_Quarter_Last_Day'

-- Get the First Day of Last Quarter
SELECT Dateadd(qq, Datediff(qq,0,GetDate())-1, 0) AS 'Last_Quarter_First_Day'

-- Get the Last Day of Last Quarter
SELECT Dateadd(ms,-3,Dateadd(qq, Datediff(qq,0,GetDate()), 0)) AS 'Last_Quarter_Last_Day'

------------------------- Year ------------------------

-- Get the First Day of Current Year
SELECT DATEADD(yy,DATEDIFF(yy,0,GETDATE()),0) AS 'Current_Year_First_Day'

-- Get the Last Day of Current Year
SELECT DATEADD(ms,-3,DATEADD(yy,0,DATEADD(yy,DATEDIFF(yy,0,GETDATE())+1,0))) AS 'Current_Year_Last_Day'

-- Get the First Day of Last Year
SELECT DATEADD(yy,-1,DATEADD(yy,DATEDIFF(yy,0,GETDATE()),0)) AS 'Last_Year_First_Day'

-- Get the Last Day of Last Year
SELECT DATEADD(ms,-3,DATEADD(yy,0,DATEADD(yy,DATEDIFF(yy,0,GETDATE()),0))) AS 'Last_Year_Last_Day'

 

Logic Explained:

When you are asked to write a query in an interview, you need not give the exact output rather you are expected to give the logic. The person who understands the base logic can easily implement a solution for any given requirement. Now let’s try to understand the logic.

Here ‘0’ indicates the starting date in the data time range. i.e : 1900-01-01 00:00:00.000

SELECT DATEADD (DD, 0, 0);

Now we’ll see how to get the first day of current week:

SELECT DATEADD (wk, DATEDIFF (wk, 0, GETDATE ()),0) AS ‘Current_Week_First_Day’

DATEDIFF (wk, 0, GETDATE()): First we are capturing the total number of weeks between the start date in date range (1900-01-01) and the current date (Based on the GTEDATE). For example today’s date is 24-Jan-17 then the difference will be (SELECT DATEDIFF (wk, 0, ‘2017-01-24’) ; 6108.

DATEADD (wk, DATEDIFF (wk, 0, GETDATE ()), 0): We have calculated the inner value as 6108. Now we simply add the number of weeks to the start date then it fetch the 6108 week starting date. i.e.: SELECT DATEADD (wk, 6108, 0); returns the week start date as “2017-01-23 00:00:00.000”

SQL Server Date and Time related Interview Questions  Download the T-SQL script file.

Posted in Interview Q&A, SQL Development, SQL Scripts | Tagged , , , , | 2 Comments