Adsense

Friday, May 1, 2015

Update use SIDS following a SQL Server Restore


declare @usrname varchar(100), @command varchar(100)
declare Crs insensitive cursor for
select name as UserName from sysusers
where issqluser = 1 and (sid is not null and sid <> 0x0)
and suser_sname(sid) is null
order by name
for read only
open Crs
fetch next from Crs into @usrname

while @@fetch_status=0
begin
select @command= 'exec sp_change_users_login @action ='+''''+ 'auto_fix' + '''' + ',@UserNamePattern='+''''+ @usrname+''''
print @command
exec(@command)
fetch next from Crs into @usrname
end
close Crs
deallocate Crs



Estimate Size of a SQL Server Table

If you're curious how large a SQL Server table will get use the below script to estimate the size after updating the table name, estimated number of records, and the freespace in your database.

set nocount on

declare @freespace as numeric(4, 2)
declare @page_space_available as bigint
declare @estimated_records_after_one_year as bigint
declare @table_name as sysname
declare @max_record_size as bigint
declare @records_per_page as bigint
declare @total_datapages as bigint
declare @RID_size as bigint

/*******************************************************************/
/********update these variables to get estimated space usage********/
/*******************************************************************/
/*****/set @freespace = 0.1                                   /*****/
/*****/set @estimated_records_after_one_year= 3000000         /*****/
/*****/set @table_name = 'TABLE NAME'                         /*****/
/*******************************************************************/
/*******************************************************************/
/*******************************************************************/

/*A datapage is 8192 bytes, but up to 132 bytes of that can be the header leaving just 8060 bytes for data*/
set @page_space_available = 8060 * (1.0 - @freespace)

if not exists (select 1 from sys.objects where name = @table_name and type = 'u')
       raiserror ('Table does not exist.', 16, 1)

else
begin
       if exists (select 1 from sys.indexes si inner join sys.objects so on so.object_id = si.object_id where so.type = 'u' and so.name = @table_name and si.index_id = 0)
       begin
              raiserror ('This table is a HEAP and space estimate could be off due to forwarded records, you should consider adding a clustered index.', 16, 1)
       end

       if exists (select 1 from sys.columns c inner join sys.objects o on o.object_id = c.object_id and o.name = @table_name and o.type = 'u' and c.max_length = -1)
       begin
              raiserror ('This table contains datatypes which do not live on the datapage - such as varchar(max) or xml - this estimate is not entirely valid since those datatype could reach an infinite size.', 16, 1)
       end

       select @max_record_size = sum(case c.max_length when -1 then 10000 else c.max_length end)
       from sys.columns c
       inner join sys.objects o on o.object_id = c.object_id
       and o.name = @table_name
       and o.type = 'u'

       if @max_record_size > @page_space_available
       begin
              select 'This table contains a datatype which may not live on a datapage so these results should be taken with a grain of salt' as message

              set @max_record_size = @page_space_available
       end

       set @records_per_page = @page_space_available / @max_record_size

       set @total_datapages = @estimated_records_after_one_year / @records_per_page

       select (@total_datapages * 8192) / (1048576) as estimated_table_space_used_in_mb

       --If there is a clustered index then grab the size of it in bytes
       if exists (select 1 from sys.indexes si inner join sys.objects so on so.object_id = si.object_id where so.type = 'u' and so.name = @table_name and si.index_id = 1)
       begin
              select @RID_size = sum(sc.max_length)
              from sys.indexes si
              inner join sys.objects so on so.object_id = si.object_id
              inner join sys.sysindexkeys sik on sik.id = so.object_id and sik.indid = si.index_id
              inner join sys.columns sc on sc.object_id = so.object_id and sc.column_id = sik.colid
              where so.type = 'u'
              and so.name = @table_name
              and si.index_id = 1
       end
       else
       begin
              select @RID_size = 16 /*setting this to 16 bytes if the table is a HEAP - it's not necessarily 16 bytes but I think
                                           thats a good estimage for the file identifier, page number, and row number.*/
       end

       select sum(max_length) as estimated_index_space_used_in_mb
       from (
              select ((@estimated_records_after_one_year / (@page_space_available / (sum(sc.max_length) + @RID_size))) * 8192) / (1048576) as max_length -- include a constant for nonclustered key value and a row locator
              from sys.indexes si
              inner join sys.objects so on so.object_id = si.object_id
              inner join sys.sysindexkeys sik on sik.id = so.object_id and sik.indid = si.index_id
              inner join sys.columns sc on sc.object_id = so.object_id and sc.column_id = sik.colid
              where so.type = 'u'
              and so.name = @table_name
              and si.index_id <> 1 --Do not include the clustered index
              and si.index_id <> 0 --Do not include heaps
              group by si.name) t
end



Script to Create a Script that Will Drop and Add all Foreign Keys in a SQL Server Database

   select 'ALTER TABLE ' + cast(c.name as  varchar(255))  + '
        DROP CONSTRAINT ' + cast(f.name  as varchar(255))
    from sysobjects f
    inner join sysobjects c on  f.parent_obj = c.id
    inner join sysreferences r on f.id =  r.constid
    inner join sysobjects p on r.rkeyid = p.id
    inner  join syscolumns rc on r.rkeyid = rc.id and r.rkey1 = rc.colid
    inner  join syscolumns fc on r.fkeyid = fc.id and r.fkey1 = fc.colid
    left join  syscolumns rc2 on r.rkeyid = rc2.id and r.rkey2 = rc.colid
    left join  syscolumns fc2 on r.fkeyid = fc2.id and r.fkey2 = fc.colid
    where f.type =  'F'


select 'ALTER TABLE ' + cast(c.name as  varchar(255)) + ' ADD CONSTRAINT ' + cast(f.name  as varchar(255)) + '
            FOREIGN KEY (' + cast(fc.name as varchar(255)) + ')
            REFERENCES ' + cast(p.name as varchar(255)) + ' (' + cast(rc.name as varchar(255)) + ')'
    from sysobjects f
    inner join sysobjects c on  f.parent_obj = c.id
    inner join sysreferences r on f.id =  r.constid
    inner join sysobjects p on r.rkeyid = p.id
    inner  join syscolumns rc on r.rkeyid = rc.id and r.rkey1 = rc.colid
    inner  join syscolumns fc on r.fkeyid = fc.id and r.fkey1 = fc.colid
    left join  syscolumns rc2 on r.rkeyid = rc2.id and r.rkey2 = rc.colid
    left join  syscolumns fc2 on r.fkeyid = fc2.id and r.fkey2 = fc.colid
    where f.type =  'F'



Create a Comma Separated Column List for a SQL Server Table

declare @t as varchar(100)
declare @all as varchar(4000)

declare curs cursor for
select rtrim(c.name) + ', '
from sysobjects o
inner join syscolumns c on o.id = c.id
where o.xtype = 'u'
and o.name = 'table_name'
order by colid

open curs

fetch next from curs into @t

set @all = ''

while @@fetch_status = 0
begin

       set @all = @all + @t

       fetch next from curs into @t

end

close curs

deallocate curs

print @all


Average Run Time of a SQL Server Job

To get the average run time of a SQL Server job the below code will get that information from sysjobhistory.

SELECT
       name,
       start_time,
       dateadd(s, avg(run_duration_seconds), start_time) as average_end_time,
       dateadd(s, max(run_duration_seconds), start_time) as max_end_time,
       dateadd(s, min(run_duration_seconds), start_time) as min_end_time
FROM
       (SELECT
              j.name,
              cast('01/01/1900 ' +
              substring(right(('000000') + cast(jh.run_time as varchar), 6), 1, 2) + ':' +
              substring(right(('000000') + cast(jh.run_time as varchar), 6), 3, 2) + ':' +
              substring(right(('000000') + cast(jh.run_time as varchar), 6), 5, 2) as smalldatetime) as start_time,
              substring(right(('000000') + cast(jh.run_duration as varchar), 6), 5, 2) +
              (substring(right(('000000') + cast(jh.run_duration as varchar), 6), 3, 2) * 60) +
              (substring(right(('000000') + cast(jh.run_duration as varchar), 6), 1, 2) * 60 * 60) as run_duration_seconds
       FROM sysjobs j
              INNER JOIN sysjobhistory jh on j.job_id = jh.job_id
       WHERE
              datepart(weekday, cast(substring(cast(jh.run_date as varchar), 5, 2) + '-' + substring(cast(jh.run_date as varchar), 7, 2) + '-' + substring(cast(jh.run_date as varchar), 1, 4) as smalldatetime)) in (2,3,4,5,6)
WHERE run_duration_seconds > 120
GROUP BY
       name,
       start_time
ORDER BY
       name


Script out Permissions

If you want to copy permissions from one database to another the following script will handle migration of roles, role members, object permissions, and database owners.


set nocount on

declare @DBName varchar(100)

DECLARE curs CURSOR for
SELECT distinct name
FROM master.dbo.SYSDATABASES
where dbid > 4

OPEN CURS

FETCH Next FROM CURS into @dbname

WHILE @@FETCH_STATUS = 0
BEGIN     
        
       EXEC('         
        SELECT ''IF NOT EXISTS(SELECT 1 FROM ' + @DBName + '..sysusers where name='''''' + sysusers.Name + '''''')'' + CHAR(13) +  ''EXEC ' + @DBName + '..sp_grantdbaccess '''''' + syslogins.name + '''''', '''''' + sysusers.name + ''''''''         
         FROM ' + @DBName + '..sysusers sysusers         
         JOIN master..syslogins syslogins         
           ON syslogins.sid=sysusers.sid         
        WHERE issqlrole=0         
          AND sysusers.Name Not in (''Guest'', ''dbo'')         
       ')     
            
       --Roles     
       EXEC('     
       SELECT ''IF NOT EXISTS(SELECT 1 FROM ' + @DBName + '..sysusers where name='''''' + Name + '''''' and issqlrole=1)'' + CHAR(13) + ''exec ' + @DBName + '..sp_addrole '''''' + Name + '''''', ''''dbo''''''     
         FROM ' + @DBName + '..sysusers      
        WHERE issqlrole=1      
          AND name not like ''db_%''     
       ')     
            
       --Role Members         
            
       EXEC('         
       SELECT ''EXEC ' + @DBName + '..sp_addrolemember '''''' + role.name + '''''', '''''' + member.name + ''''''''         
         FROM ' + @DBName + '..sysmembers sysmembers         
         JOIN ' + @DBName + '..sysusers role         
           ON groupuid=role.uid         
         JOIN ' + @DBName + '..sysusers member         
           ON memberuid=member.uid         
        WHERE member.name<>''dbo''         
       ')     
             
       --Object Permissions         
       EXEC('         
       SELECT ''USE ' + @DBName + ''' + CHAR(13) +      
        ''IF EXISTS(SELECT 1 FROM ' + @DBName + '..sysobjects where name='''''' + o.name + '''''')'' + CHAR(13) +      
        ''GRANT '' + v.name + '' ON '' + u2.name + ''.'' + o.name + '' TO ['' + u1.name + '']''     
         FROM ' + @DBName + '..sysprotects p          
         JOIN master..spt_values v         
           ON action = v.number          
          AND v.type = ''T''         
         JOIN ' + @DBName + '..sysobjects o         
           ON o.id = p.id         
         JOIN ' + @DBName + '..sysusers u1         
           ON u1.uid=p.uid         
         JOIN ' + @DBName + '..sysusers u2         
           ON u2.uid=o.uid         
        WHERE p.id > 100         
          AND protecttype IN  (204,205)         
       ')     
            
       --Set DB owner     
         
            
        EXEC('    
        SELECT ''exec ' + @DBName + '..sp_changedbowner ''''sa''''''     
        ')   
      
       FETCH Next FROM CURS into @dbname
END     
   
close curs     
DEALLOCATE curs