Need help in automating using tsql

  • Hi All,

    I have a small requirement. We have Prod and non-prod environments.

    We do get requests to refresh the non-prods environments monthly 6 times and its quite a time consuming task.

    It usually takes around 4 hours to complete the refresh activity. Looking for automated script which can handle below steps. If anyone has already done this before, kindly help. Its saves a lot of time.

    Refresh steps

    ==============

    step 1 : Take a copy only full backup on prod

    step 2 : I am using below script to script out existing non-prod env. for example say, I get a request to refresh DEV server, then I run below script against the database which has to be refreshed (lets say AdventureWorksDB ) and keep the output aside say in a separate output file (permissions.sql).

    /*

    Script DB Level Permissions v2.1

    Source: http://www.sqlservercentral.com/scripts/Security/71562/

    */

    DECLARE

    @sql VARCHAR(2048)

    ,@sort INT

    DECLARE tmp CURSOR FOR

    /*********************************************/

    /********* DB CONTEXT STATEMENT *********/

    /*********************************************/

    SELECT '-- [-- DB CONTEXT --] --' AS [-- SQL STATEMENTS --],

    1 AS [-- RESULT ORDER HOLDER --]

    UNION

    SELECT 'USE' + SPACE(1) + QUOTENAME(DB_NAME()) AS [-- SQL STATEMENTS --],

    1 AS [-- RESULT ORDER HOLDER --]

    UNION

    SELECT '' AS [-- SQL STATEMENTS --],

    2 AS [-- RESULT ORDER HOLDER --]

    UNION

    /*********************************************/

    /********* DB USER CREATION *********/

    /*********************************************/

    SELECT '-- [-- DB USERS --] --' AS [-- SQL STATEMENTS --],

    3 AS [-- RESULT ORDER HOLDER --]

    UNION

    SELECT 'IF NOT EXISTS (SELECT [name] FROM sys.database_principals WHERE [name] = ' + SPACE(1) + '''' + [name] + '''' + ') BEGIN CREATE USER ' + SPACE(1) + QUOTENAME([name]) + ' FOR LOGIN ' + QUOTENAME([name]) + ' WITH DEFAULT_SCHEMA = ' + QUOTENAME([default_schema_name]) + SPACE(1) + 'END; ' AS [-- SQL STATEMENTS --],

    4 AS [-- RESULT ORDER HOLDER --]

    FROM sys.database_principals AS rm

    WHERE [type] IN ('U', 'S', 'G') -- windows users, sql users, windows groups

    UNION

    /*********************************************/

    /********* DB ROLE PERMISSIONS *********/

    /*********************************************/

    SELECT '-- [-- DB ROLES --] --' AS [-- SQL STATEMENTS --],

    5 AS [-- RESULT ORDER HOLDER --]

    UNION

    SELECT 'EXEC sp_addrolemember @rolename ='

    + SPACE(1) + QUOTENAME(USER_NAME(rm.role_principal_id), '''') + ', @membername =' + SPACE(1) + QUOTENAME(USER_NAME(rm.member_principal_id), '''') AS [-- SQL STATEMENTS --],

    6 AS [-- RESULT ORDER HOLDER --]

    FROM sys.database_role_members AS rm

    WHERE USER_NAME(rm.member_principal_id) IN (

    --get user names on the database

    SELECT [name]

    FROM sys.database_principals

    WHERE [principal_id] > 4 -- 0 to 4 are system users/schemas

    and [type] IN ('G', 'S', 'U') -- S = SQL user, U = Windows user, G = Windows group

    )

    --ORDER BY rm.role_principal_id ASC

    UNION

    SELECT '' AS [-- SQL STATEMENTS --],

    7 AS [-- RESULT ORDER HOLDER --]

    UNION

    /*********************************************/

    /********* OBJECT LEVEL PERMISSIONS *********/

    /*********************************************/

    SELECT '-- [-- OBJECT LEVEL PERMISSIONS --] --' AS [-- SQL STATEMENTS --],

    8 AS [-- RESULT ORDER HOLDER --]

    UNION

    SELECT CASE

    WHEN perm.state <> 'W' THEN perm.state_desc

    ELSE 'GRANT'

    END

    + SPACE(1) + perm.permission_name + SPACE(1) + 'ON ' + QUOTENAME(SCHEMA_NAME(obj.schema_id)) + '.' + QUOTENAME(obj.name) --select, execute, etc on specific objects

    + CASE

    WHEN cl.column_id IS NULL THEN SPACE(0)

    ELSE '(' + QUOTENAME(cl.name) + ')'

    END

    + SPACE(1) + 'TO' + SPACE(1) + QUOTENAME(USER_NAME(usr.principal_id)) COLLATE database_default

    + CASE

    WHEN perm.state <> 'W' THEN SPACE(0)

    ELSE SPACE(1) + 'WITH GRANT OPTION'

    END

    AS [-- SQL STATEMENTS --],

    9 AS [-- RESULT ORDER HOLDER --]

    FROM

    sys.database_permissions AS perm

    INNER JOIN

    sys.objects AS obj

    ON perm.major_id = obj.[object_id]

    INNER JOIN

    sys.database_principals AS usr

    ON perm.grantee_principal_id = usr.principal_id

    LEFT JOIN

    sys.columns AS cl

    ON cl.column_id = perm.minor_id AND cl.[object_id] = perm.major_id

    --WHERE usr.name = @OldUser

    --ORDER BY perm.permission_name ASC, perm.state_desc ASC

    UNION

    SELECT '' AS [-- SQL STATEMENTS --],

    10 AS [-- RESULT ORDER HOLDER --]

    UNION

    /*********************************************/

    /********* DB LEVEL PERMISSIONS *********/

    /*********************************************/

    SELECT '-- [--DB LEVEL PERMISSIONS --] --' AS [-- SQL STATEMENTS --],

    11 AS [-- RESULT ORDER HOLDER --]

    UNION

    SELECT CASE

    WHEN perm.state <> 'W' THEN perm.state_desc --W=Grant With Grant Option

    ELSE 'GRANT'

    END

    + SPACE(1) + perm.permission_name --CONNECT, etc

    + SPACE(1) + 'TO' + SPACE(1) + '[' + USER_NAME(usr.principal_id) + ']' COLLATE database_default --TO <user name>

    + CASE

    WHEN perm.state <> 'W' THEN SPACE(0)

    ELSE SPACE(1) + 'WITH GRANT OPTION'

    END

    AS [-- SQL STATEMENTS --],

    12 AS [-- RESULT ORDER HOLDER --]

    FROM sys.database_permissions AS perm

    INNER JOIN

    sys.database_principals AS usr

    ON perm.grantee_principal_id = usr.principal_id

    --WHERE usr.name = @OldUser

    WHERE [perm].[major_id] = 0

    AND [usr].[principal_id] > 4 -- 0 to 4 are system users/schemas

    AND [usr].[type] IN ('G', 'S', 'U') -- S = SQL user, U = Windows user, G = Windows group

    UNION

    SELECT '' AS [-- SQL STATEMENTS --],

    13 AS [-- RESULT ORDER HOLDER --]

    UNION

    SELECT '-- [--DB LEVEL SCHEMA PERMISSIONS --] --' AS [-- SQL STATEMENTS --],

    14 AS [-- RESULT ORDER HOLDER --]

    UNION

    SELECT CASE

    WHEN perm.state <> 'W' THEN perm.state_desc --W=Grant With Grant Option

    ELSE 'GRANT'

    END

    + SPACE(1) + perm.permission_name --CONNECT, etc

    + SPACE(1) + 'ON' + SPACE(1) + class_desc + '::' COLLATE database_default --TO <user name>

    + QUOTENAME(SCHEMA_NAME(major_id))

    + SPACE(1) + 'TO' + SPACE(1) + QUOTENAME(USER_NAME(grantee_principal_id)) COLLATE database_default

    + CASE

    WHEN perm.state <> 'W' THEN SPACE(0)

    ELSE SPACE(1) + 'WITH GRANT OPTION'

    END

    AS [-- SQL STATEMENTS --],

    15 AS [-- RESULT ORDER HOLDER --]

    from sys.database_permissions AS perm

    inner join sys.schemas s

    on perm.major_id = s.schema_id

    inner join sys.database_principals dbprin

    on perm.grantee_principal_id = dbprin.principal_id

    WHERE class = 3 --class 3 = schema

    ORDER BY [-- RESULT ORDER HOLDER --]

    OPEN tmp

    FETCH NEXT FROM tmp INTO @sql, @sort

    WHILE @@FETCH_STATUS = 0

    BEGIN

    PRINT @sql

    FETCH NEXT FROM tmp INTO @sql, @sort

    END

    CLOSE tmp

    DEALLOCATE tmp

    Step 3 :

    =======

    Next, I will copy over the above full backup from prod server to DEV server locally and perform the restore on DEV server.

    IMP NOTE: The filepaths are different on DEV SERVER but logical name and filename are the same.

    So, while restoring we need to change the path n perform the restore. For this, I am looking for dynamic script which dynamically gets the file paths of that respective server (say DEV,QA etc... based whatever value i send as input to the script or variable inside the automation script.

    Step 4:

    =======

    Once restore is done, i need to run the output (i.e. permissions output from Step2 ) against the restored database on non-prod server(DEV/QA).

    Step 5:

    =========

    Finally, we need to change the recovery model of the database to SIMPLE as it is non-prod env

    How can we accomplish this using plain TSQL automated script/stored proc.

    Thank you.

    Sam

  • If you already have a process, what's wrong with what you have? It doesn't seem to be that time consuming; run a back up, restore it (on a different server) and then run a script; that's only 3 steps and you can do other things while you do that.

    If this is a very frequent task, have you considered using tools that do this kind of thing? I admit, they aren't cheap, but Redgate (for example) has tools that appear to do what you need; such as SQL Clone (and perhaps Data Masker).

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • Try using this... It is free and customizable. You can simply setup a job with this command and run.

    https://docs.dbatools.io/#Copy-DbaDatabase

     

  • How about having a shared location, sort of a DMZ, since the DEV cannot see the PROD by design.

    A scheduled agent task / job at the destination can run an SSIS package to grab the nightly DB backup file(s) (if that is the case) from that shared location and restore at the destination.

    Of course you would need to add a line or 2 in your script to get the DB in single user mode prior to restoring while using the Master DB for restorations with recovery.

    Of course there are many possible methods as some of the folks here mentioned.

     

    Cheers,
    John Esraelo

  • Thanks for all the inputs.

  • vsamantha35 wrote:

    Thanks for all the inputs.

    What solved your problem here? Rather than just saying "thanks" if you let us know what solution you used it'll help people in the future with the same/similar problem.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

Viewing 6 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic. Login to reply