Selecting from and Limiting SHOW statements – SNOWFLAKE

September 13, 2023

The example code below demonstrates how to select columns/limit results via the where clause using SHOW statements on Snowflake. A key point is that in the final select statement, field names must be enclosed in quotes otherwise the statement will fail. You will also be able to use the below methodology to join on the result set.

The code below returns the max number of clusters available to a warehouse

show warehouses;

show warehouses;
SET query_id= last_query_id(); –specific to current session
SELECT “max_cluster_count” FROM TABLE(RESULT_SCAN($query_id)) where “name” = ‘WAREHOUSE_NAME’ –field names must be enclosed in quotes, code will fail without

comma separated list and get_ddl – snowflake

July 26, 2023
select array_to_string(arrayagg(column_name) within group (order by ordinal_position),',')
from DB.information_schema.columns
where table_name = 'TABLE NAME'


select get_ddl('table','DB.SCHEMA.TABLE');

Download all contents of S3 bucket

February 22, 2023

import boto3

import os

s3 = boto3.resource('s3') 

bucket = s3.Bucket('YOUR BUCKET HERE')
local_target = 'C:\\temp\pyTest'

for object in bucket.objects.all():

    #print(os.path.split(local_target + '/' + object.key))

    if not os.path.exists(os.path.split(local_target + '/' + object.key)[0]):

            os.makedirs(os.path.split(local_target + '/' + object.key)[0])

    #print (object.key)

    if not object.key.endswith('/'):

        bucket.download_file(object.key,local_target + '\\' + os.path.split(object.key)[0]+ '\\' + os.path.split(object.key)[1])

Pull each file from a given list from an S3 bucket

February 22, 2023

import boto3

files=[]
listOfFiles =  open('c:/temp/dl.txt') #a list of files you want to download, seperated by a new line

for line in listOfFiles:
    files.append(line.strip()) #read each file into a list

print (f'{files=}')

s3 = boto3.resource('s3') 
bucket = s3.Bucket('YOUR BUCKET NAME HERE') #if you are awsuming make sure you are using the right profile

for file in files:
    print(file)
    key = 'SUBFOLDER(S) HERE/' + file
    print(f'{key=}')
    dest = 'C:\\temp\\pyTest\\' + file #local destination
    print(f'{dest=}')
    bucket.download_file(key,dest)

Updated script – Move data off filegroup

December 18, 2022



CREATE procedure [dbo].[sp_getIndexes]

	@move_to VARCHAR(1000) = NULL, --which filegroup are you moving index to?
	@table VARCHAR(1000) = '%',
	@schema VARCHAR(1000) = '%'


AS

SELECT 

		a.object_id,
		a.index_id,
		'CREATE ' + 
		CASE is_unique WHEN 1 THEN ' UNIQUE ' ELSE + '' END +
		a.type_desc + 
		' INDEX ' + 
		QUOTENAME(a.name) COLLATE DATABASE_DEFAULT +
		' ON ' +
		QUOTENAME(c.name) + '.' +
		QUOTENAME(b.name) + 
		e.index_cols +

		ISNULL(f.included_cols,'') + 

		CASE WHEN filter_definition IS NOT NULL THEN ' WHERE ' +  filter_definition   +
			')'		ELSE ''	END +

		' WITH (FILLFACTOR='+
			CAST(fill_factor AS VARCHAR(5)) + 

			' ,SORT_IN_TEMPDB = ON, DROP_EXISTING = ON, DATA_COMPRESSION = '+ data_compression_desc +')' +

		' ON ' + 
			quotename(ISNULL(@move_to,d.name))   AS create_script






FROM sys.indexes a (NOLOCK)
INNER JOIN sys.all_objects b  (NOLOCK)on a.object_id = b.object_id
inner join sys.schemas c  (NOLOCK)on c.schema_id = b.schema_id
INNER JOIN sys.data_spaces d  (NOLOCK)on d.data_space_id = a.data_space_id

INNER JOIN (

				SELECT  DISTINCT a.object_id,index_id ,
						'(' + STUFF((
						SELECT ',' + QUOTENAME([name]) + CASE a.is_descending_key WHEN 1 THEN ' DESC' ELSE '' END as [text()] 
						FROM sys.columns b  (NOLOCK)
						INNER JOIN sys.index_COLUMNS c on c.column_id = b.column_id and b.object_id = c.object_id
						WHERE a.object_id = b.object_id and c.index_id = a.index_id and c.is_included_column = 0
						ORDER BY c.key_ordinal
						FOR XML PATH ('')),1,1,'') + ')' index_cols
		

				FROM sys.index_COLUMNS a (NOLOCK)

			) e on e.object_id = a.object_id AND e.index_id = a.index_id

			LEFT JOIN (

				SELECT  DISTINCT a.object_id,index_id ,
						' INCLUDE (' + STUFF((
						SELECT ',' + QUOTENAME([name])  as [text()] 
						FROM sys.columns b  (NOLOCK)
						INNER JOIN sys.index_COLUMNS c on c.column_id = b.column_id and b.object_id = c.object_id
						WHERE a.object_id = b.object_id and c.index_id = a.index_id and c.is_included_column = 1
						ORDER BY a.key_ordinal
						FOR XML PATH ('')),1,1,'') + ')' included_cols
		

				FROM sys.index_COLUMNS a (NOLOCK)

			) f on f.object_id = a.object_id AND f.index_id = a.index_id

INNER JOIN sys.partitions g (NOLOCK) on g.object_id = a.object_id and g.index_id = a.index_id

where	a.index_id >0 and 
		c.name != 'sys' and 
		b.name like '%'+@table +'%'and 
		c.name like '%'+@schema +'%'


UNION ALL

SELECT 

		a.object_id,
		a.index_id,
		'CREATE ' + 
		CASE is_unique WHEN 1 THEN ' UNIQUE ' ELSE + '' END +
		a.type_desc + 
		' INDEX ' + 
		QUOTENAME(a.name) COLLATE DATABASE_DEFAULT +
		' ON ' +
		QUOTENAME(c.name) + '.' +
		QUOTENAME(b.name) + 
		ISNULL(f.included_cols,'') + 
		CASE WHEN filter_definition IS NOT NULL THEN ' WHERE ' +  filter_definition   +
			')'		ELSE ''	END +
		' WITH (DROP_EXISTING = ON)' +
		' ON ' + 
			QUOTENAME(ISNULL(@move_to,d.name))  AS create_script

FROM sys.indexes a (NOLOCK)
INNER JOIN sys.all_objects b  (NOLOCK)on a.object_id = b.object_id
inner join sys.schemas c  (NOLOCK)on c.schema_id = b.schema_id
INNER JOIN sys.data_spaces d  (NOLOCK)on d.data_space_id = a.data_space_id

LEFT JOIN (

				SELECT  DISTINCT a.object_id,index_id ,
						'(' + STUFF((
						SELECT ',' + QUOTENAME([name]) + CASE a.is_descending_key WHEN 1 THEN ' DESC' ELSE '' END as [text()] 
						FROM sys.columns b  (NOLOCK)
						INNER JOIN sys.index_COLUMNS c on c.column_id = b.column_id and b.object_id = c.object_id
						WHERE a.object_id = b.object_id and c.index_id = a.index_id
						ORDER BY a.key_ordinal
						FOR XML PATH ('')),1,1,'') + ')' index_cols
		

				FROM sys.index_COLUMNS a (NOLOCK)
				WHERE is_included_column = 0

			) e on e.object_id = a.object_id AND e.index_id = a.index_id

			LEFT JOIN (

				SELECT  DISTINCT a.object_id,index_id ,
						' (' + STUFF((
						SELECT ',' + QUOTENAME([name])  as [text()] 
						FROM sys.columns b  (NOLOCK)
						INNER JOIN sys.index_COLUMNS c on c.column_id = b.column_id and b.object_id = c.object_id
						WHERE a.object_id = b.object_id and c.index_id = a.index_id
						ORDER BY a.key_ordinal
						FOR XML PATH ('')),1,1,'') + ')' included_cols
		

				FROM sys.index_COLUMNS a (NOLOCK)
				WHERE is_included_column = 1

			) f on f.object_id = a.object_id AND f.index_id = a.index_id

INNER JOIN sys.partitions g (NOLOCK) on g.object_id = a.object_id and g.index_id = a.index_id

where	a.type = 6 and 
		c.name != 'sys' and 
		b.name like '%'+@table +'%' and
		c.name like '%'+@schema +'%'


















declare @move_from VARCHAR(100) = 'DATA1' 	--filesgroup to move data off
declare @move_to VARCHAR(100)	 = 'DATA'	--filesgroup to move data off


IF OBJECT_ID('tempdb..#result_set') IS NOT NULL DROP TABLE #result_set
CREATE TABLE #result_set(object_id bigint, index_id int, script VARCHAR(MAX))
INSERT INTO #result_set
exec sp_getIndexes @move_to = @move_to

select b.script,f.name lob_fg,g.name data_fg
from sys.indexes a 
left join #result_set  b on a.object_id = b.object_id and a.index_id = b.index_id
inner join sys.objects c on c.object_id = a.object_id
inner join sys.schemas d on d.schema_id = c.schema_id
inner join sys.tables e on e.object_id = b.object_id
left join sys.data_spaces f on f.data_space_id = e.lob_data_space_id
left join sys.data_spaces g on g.data_space_id = a.data_space_id
where	(
			d.name != 'sys' and 
			g.name = ISNULL(@move_from ,g.name) and 
			g.name != isnull(@move_to,g.name) and  
			1=1
		)
		OR
		(f.name = @move_from and a.index_id>1)

UNION ALL

select 'CREATE CLUSTERED INDEX [x] on ' + QUOTENAME(schema_name) + '.' + QUOTENAME(table_name) + '(' + QUOTENAME(column_name) + ')  WITH(SORT_IN_TEMPDB=ON,DATA_COMPRESSION=PAGE) ON ' + QUOTENAME(@move_to) + '
DROP INDEX [x] ON ' + QUOTENAME(schema_name) + '.' + QUOTENAME(table_name), lob_fg,data_fg
from (
select b.name table_name,c.name schema_name,d.name column_name,row_number() over (partition by d.object_id order by column_id) r 
 ,f.name lob_fg, e.name data_fg
from sys.indexes a (NOLOCK)
inner join sys.tables b (NOLOCK) on a.object_id = b.object_id
inner join sys.schemas c (NOLOCK) on c.schema_id = b.schema_id
inner join sys.columns d (NOLOCK) on d.object_id = b.object_id
inner join sys.data_spaces e (NOLOCK) on e.data_space_id = a.data_space_id
left join sys.data_spaces f (NOLOCK) on f.data_space_id = b.lob_data_space_id
where index_id = 0 and e.name = @move_from and ISNULL(f.name,'') != @move_from) x
where r = 1 

UNION ALL

SELECT 'CREATE PARTITION FUNCTION '+schema_name+'_' + table_name +'('+

				CASE	data_type
						WHEN 'VARCHAR' THEN 'VARCHAR('+ CAST(max_length AS VARCHAR(10)) + ')'
						WHEN 'NVARCHAR' THEN 'NVARCHAR('+ CAST(max_length/2 AS VARCHAR(10)) + ')'
						WHEN 'NUMERIC' THEN 'NUMERIC('+ CAST(precision AS VARCHAR(10)) + ','+ CAST(scale AS VARCHAR(10))+')'


						ELSE  data_type
				END
					
					
					
				+') AS RANGE RIGHT FOR VALUES ('+

			CASE data_type  
			
					WHEN 'int' THEN CAST(0 AS VARCHAR(1))
					WHEN 'numeric' THEN CAST(0 AS VARCHAR(1))
					WHEN 'BIT' THEN CAST(0 AS VARCHAR(1))
					WHEN 'DATE' THEN ''''+CAST('20300101' AS VARCHAR(10))+''''
					WHEN 'DATETIME' THEN ''''+CAST('20300101' AS VARCHAR(10))+''''
					WHEN 'DATETIME2' THEN ''''+CAST('20300101' AS VARCHAR(10))+''''
					WHEN 'VARCHAR' THEN ''''''
					WHEN 'NVARCHAR' THEN ''''''
			END
					+')
CREATE PARTITION SCHEME '+schema_name+'_' + table_name +' AS PARTITION '+schema_name+'_' + table_name +' to ('+QUOTENAME(@move_to)+','+QUOTENAME(@move_to)+')					
CREATE CLUSTERED INDEX '+schema_name+'_' + table_name +' ON '+QUOTENAME(schema_name)+'.' + QUOTENAME(table_name) + '(' +column_name +') with (sort_in_tempdb = on,DATA_COMPRESSION=PAGE) on ' +schema_name +'_' + table_name + '(' +column_name +')
CREATE CLUSTERED INDEX '+schema_name+'_' + table_name +' ON '+QUOTENAME(schema_name)+'.' + QUOTENAME(table_name) + '(' +column_name +') with (drop_existing = on,sort_in_tempdb = on,DATA_COMPRESSION=PAGE) on  ' + QUOTENAME(@move_to) + '
DROP  INDEX '+schema_name+'_' + table_name +' ON '+QUOTENAME(schema_name)+'.' + QUOTENAME(table_name) +'
DROP PARTITION SCHEME '+schema_name+'_' + table_name +'					
DROP PARTITION FUNCTION '+schema_name+'_' + table_name					,lob_fg,data_fg
FROM (
select b.name table_name,c.name schema_name,d.name column_name,row_number() over (partition by d.object_id order by column_id) r 
 ,f.name lob_fg, e.name data_fg,g.name data_type,d.max_length,d.precision,d.scale
from sys.indexes a (NOLOCK)
inner join sys.tables b (NOLOCK) on a.object_id = b.object_id
inner join sys.schemas c (NOLOCK) on c.schema_id = b.schema_id
inner join sys.columns d (NOLOCK) on d.object_id = b.object_id
inner join sys.data_spaces e (NOLOCK) on e.data_space_id = a.data_space_id
left join sys.data_spaces f (NOLOCK) on f.data_space_id = b.lob_data_space_id
inner join sys.types g (NOLOCK) ON g.system_type_id = d.system_type_id 
where ISNULL(f.name,'') = @move_from
		AND g.name != 'varchar' AND d.max_length !=-1
		AND a.index_id = 0
) x
where r = 1 

UNION ALL

SELECT 'CREATE PARTITION FUNCTION '+schema_name+'_' + table_name +'('+

				CASE	data_type
						WHEN 'VARCHAR' THEN 'VARCHAR('+ CAST(max_length AS VARCHAR(10)) + ')'
						WHEN 'NVARCHAR' THEN 'NVARCHAR('+ CAST(max_length/2 AS VARCHAR(10)) + ')'
						WHEN 'NUMERIC' THEN 'NUMERIC('+ CAST(precision AS VARCHAR(10)) + ','+ CAST(scale AS VARCHAR(10))+')'


						ELSE  data_type
				END
					
					
					
				+') AS RANGE RIGHT FOR VALUES ('+

			CASE data_type  
			
					WHEN 'int' THEN CAST(0 AS VARCHAR(1))
					WHEN 'numeric' THEN CAST(0 AS VARCHAR(1))
					WHEN 'BIT' THEN CAST(0 AS VARCHAR(1))
					WHEN 'DATE' THEN ''''+CAST('20300101' AS VARCHAR(10))+''''
					WHEN 'DATETIME' THEN ''''+CAST('20300101' AS VARCHAR(10))+''''
					WHEN 'DATETIME2' THEN ''''+CAST('20300101' AS VARCHAR(10))+''''
					WHEN 'VARCHAR' THEN ''''''
					WHEN 'NVARCHAR' THEN ''''''
			END
					+')
CREATE PARTITION SCHEME '+schema_name+'_' + table_name +' AS PARTITION '+schema_name+'_' + table_name +' to ('+QUOTENAME(@move_to)+','+QUOTENAME(@move_to)+')					
'+
replace(script,quotename(@move_to),quotename(schema_name+'_' + table_name) + '('+column_name+')' )  +'
'+
script  +'
DROP PARTITION SCHEME '+schema_name+'_' + table_name +'					
DROP PARTITION FUNCTION '+schema_name+'_' + table_name					,lob_fg,data_fg
FROM (
select b.name table_name,c.name schema_name,d.name column_name,row_number() over (partition by d.object_id order by column_id) r 
 ,f.name lob_fg, e.name data_fg,g.name data_type,d.max_length,d.precision,d.scale
 ,script
from sys.indexes a (NOLOCK)
inner join sys.tables b (NOLOCK) on a.object_id = b.object_id
inner join sys.schemas c (NOLOCK) on c.schema_id = b.schema_id
inner join sys.columns d (NOLOCK) on d.object_id = b.object_id
inner join sys.data_spaces e (NOLOCK) on e.data_space_id = a.data_space_id
left join sys.data_spaces f (NOLOCK) on f.data_space_id = b.lob_data_space_id
inner join sys.types g (NOLOCK) ON g.system_type_id = d.system_type_id 
LEFT JOIN #result_set h on h.object_id = a.object_id and h.index_id = a.index_id
where	1=1
		AND ISNULL(f.name,'') = @move_from
		AND NOT(g.name = 'varchar' AND d.max_length =-1)
		AND a.index_id = 1
		AND PATINDEX('%'+d.name+'%',  h.script)>0
) x
where r = 1 

Capturing query plans for a specific procedure

November 29, 2020

1. insert the following code or a variation into your proc

DECLARE @a VARBINARY(128) = CAST(‘jamesl’ AS VARBINARY(128)) –0x6A616D65736C

SET CONTEXT_INFO  @a

make a note of the varbinary value in this case ‘jamesl’ converts to 0x6A616D65736C


2.
place the context info value into your extended event – in this case I am grabbing all the execution plans for the procedure

Inline images 1

Scripting SSIS environments

April 7, 2020
 declare     @folder sysname = 'XXX'
 declare    @env sysname = 'XXX'



    SET NOCOUNT ON;
    DECLARE @project_id int,
            @reference_location char(1),
            @folder_description nvarchar(1024),
            @sql varchar(max) = '',
            @name sysname,
            @cr char(1) = char(10),
            @tab char(4) = SPACE(4),
            @ver nvarchar(128) = CAST(serverproperty('ProductVersion') AS nvarchar);
    SET @ver = CAST(SUBSTRING(@ver, 1, CHARINDEX('.', @ver) - 1) as int);       
    IF (@ver < 11)
    BEGIN
            RAISERROR ('This procedure is not supported on versions prior SQL 2012', 16, 1) WITH NOWAIT;
    END;
    IF NOT EXISTS(SELECT TOP 1 1 FROM sys.databases WHERE name = 'SSISDB')
    BEGIN
            RAISERROR('The SSISDB database does not exist on this server', 16, 1) WITH NOWAIT;
    END;
    /* TO DO - get the folder, environment description-*/
    SET @sql = '/**************************************************************************************' + @cr;
    SET @sql += @tab + 'This script creates a script to generate and SSIS Environment and its variables.' + @cr;
    SET @sql += @tab + 'Replace the necessary entries to create a new envrionment' + @cr;
    SET @sql += @tab + '***NOTE: variables marked as sensitive have their values masked with ''<REPLACE_ME>''.' + @cr;
    SET @sql += @tab + @tab + 'These values will need to be replace with the actual values' + @cr;
    SET @sql += '**************************************************************************************/' + @cr +@cr;
    SET @sql += 'DECLARE @ReturnCode INT=0, @folder_id bigint' + @cr + @cr;       
    SET @sql += '/*****************************************************' + @cr;
    SET @sql += @tab + 'Variable declarations, make any changes here' + @cr;
    SET @sql += '*****************************************************/' + @cr;
    SET @sql += 'DECLARE @folder sysname = ''' + @folder + ''' /* this is the name of the new folder you want to create */'  + @cr;
    SET @sql += @tab + @tab + ', @env sysname = ''' + @env + ''' /* this is the name of the new environment you want to create */';

    PRINT @sql;
    /*
            Generate the variable declarations at the "top" this makes it easier to replace/update the values
            The variable names here map to the name of the variable being created
    */
    SELECT [env_var] = @tab + @tab + ', @' + ev.name + ' '  + ev.base_data_type  + '= N''' + ISNULL(CONVERT(varchar(max), ev.value), '<REPLACE_ME>') + ''''
                    , [name] = ev.name
    INTO #env_var
    FROM [SSISDB].[catalog].[folders] f        
    INNER JOIN [SSISDB].[catalog].[environments] e ON f.folder_id =  e.folder_id        
    INNER JOIN [SSISDB].[internal].[environment_variables] ev ON e.environment_id = ev.environment_id    
    WHERE (f.name = @folder) AND (e.name = @env);
    /*
            Yes, I am looping here.  We don't know how many variables, sql_variant can be up to 8,000 bytes for the base type
            and don't want to be limited trying to print varchar(max) to the output window
            ... so we're going to print them one at a time
    */
    WHILE EXISTS (SELECT TOP 1 1 FROM #env_var)
    BEGIN
            SELECT TOP 1 @sql = env_var, @name = name FROM #env_var ORDER BY name;
            PRINT @sql;
            DELETE FROM #env_var WHERE name = @name;
    END;
    SET @sql = ';' + @cr + '/* Starting the transaction */' + @cr;
    SET @sql += 'BEGIN TRANSACTION' + @cr;                  
    SET @sql += @tab + 'IF NOT EXISTS (SELECT 1 FROM [SSISDB].[catalog].[folders] WHERE name = @folder)' + @cr;
    SET @sql += @tab + 'BEGIN' + @cr;
    SET @sql += @tab + @tab + 'RAISERROR(''Creating folder: %s ...'', 10, 1, @folder) WITH NOWAIT;' + @cr;
    SET @sql += @tab + @tab + 'EXEC @ReturnCode = [SSISDB].[catalog].[create_folder] @folder_name=@folder, @folder_id=@folder_id OUTPUT' + @cr;
    SET @sql += @tab + @tab + 'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback;' + @cr;
    SET @sql += @tab + 'END' + @cr + @cr;   
    SET @sql += @tab + 'RAISERROR(''Creating Environtment: %s'', 10, 1, @env) WITH NOWAIT;' + @cr;
    SET @sql += @tab + 'EXEC @ReturnCode = [SSISDB].[catalog].[create_environment] @folder_name=@folder, @environment_name=@env'  + @cr;
    SET @sql += @tab + 'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback;' + @cr + @cr;
    SET @sql += @tab + '/******************************************************' + @cr;
    SET @sql += @tab + @tab + 'Variable creation' + @cr;
    SET @sql += @tab + '******************************************************/' ;     
    PRINT @sql;
    /* Generate the variable creation */
    SELECT [cmd] = @tab + 'RAISERROR(''Creating variable: ' + ev.name + ' ...'', 10, 1) WITH NOWAIT;' + @cr
                                    + @tab + 'EXEC @ReturnCode = [SSISDB].[catalog].[create_environment_variable]' + @cr
                                    + @tab + @tab + '@variable_name=N''' + ev.name + '''' + @cr
                                    + @tab + @tab + ', @sensitive=' + CONVERT(varchar(2), ev.sensitive) + @cr
                                    + @tab + @tab + ', @description=N''' + ev.[description] + '''' + @cr
                                    + @tab + @tab + ', @environment_name=@env' + @cr
                                    + @tab + @tab + ', @folder_name=@folder' + @cr
                                    + @tab + @tab + ', @value=@' + ev.name + @cr
                                    + @tab + @tab + ', @data_type=N''' + ev.type + '''' + @cr
                                    + @tab + 'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback;' + @cr
                            , [name] = ev.name
    INTO #cmd
    FROM [SSISDB].[catalog].[folders] f        
    INNER JOIN [SSISDB].[catalog].[environments] e ON f.folder_id =  e.folder_id        
    INNER JOIN [SSISDB].[catalog].[environment_variables] ev ON e.environment_id = ev.environment_id    
    WHERE (f.name = @folder) AND (e.name = @env);
    /*Print out the variable creation procs */
    WHILE EXISTS (SELECT TOP 1 1 FROM #cmd)
    BEGIN
            SELECT TOP 1 @sql = cmd, @name = name FROM #cmd ORDER BY name;
            PRINT @sql;

            DELETE FROM #cmd WHERE name = @name;
    END;
    /* finsih the transaction handling */
    SET @sql = 'COMMIT TRANSACTION' + @cr;
    SET @sql += 'RAISERROR(N''Complete!'', 10, 1) WITH NOWAIT;' + @cr;
    SET @sql += 'GOTO EndSave' + @cr + @cr;
    SET @sql += 'QuitWithRollback:' + @cr;
    SET @sql += 'IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION' + @cr;
    SET @sql += 'RAISERROR(N''Variable creation failed'', 16,1) WITH NOWAIT;' + @cr + @cr;
    SET @sql += 'EndSave:' + @cr;
    SET @sql += 'GO';

    PRINT @sql;

GO

Moving from an execute as owner approach to a signed procedure approach

July 17, 2019

The following can be used as a template for signing procedures which removes the need for executing as owner and database chaining

–create a test login
CREATE LOGIN test WITH PASSWORD =’abc’, CHECK_POLICY = OFF

GO

–create a test proc

CREATE PROC test_proc
AS
SELECT * FROM sys.dm_exec_query_memory_grants

GO

GRANT EXEC ON test_proc TO PUBLIC

CREATE CERTIFICATE [CodeSigningCertificate]
ENCRYPTION BY PASSWORD = ‘Password123!’
WITH EXPIRY_DATE = ‘2099-01-01’,
SUBJECT = ‘Code Signing Cert’

CREATE LOGIN [CodeSigningLogin] FROM CERTIFICATE [CodeSigningCertificate]

GRANT VIEW SERVER STATE TO [CodeSigningLogin]
ADD SIGNATURE TO test_proc
BY CERTIFICATE [CodeSigningCertificate]
WITH PASSWORD = ‘Password123!’;

–Clean Up

/*
DROP PROC dbo.test_proc
DROP LOGIN [CodeSigningLogin]
DROP CERTIFICATE [CodeSigningCertificate]
DROP LOGIN test
*/

Mapping temp tables to users

June 28, 2019

DECLARE @FileName VARCHAR(MAX)

SELECT @FileName = SUBSTRING(path, 0,
LEN(path)-CHARINDEX(‘\’, REVERSE(path))+1) + ‘\Log.trc’
FROM sys.traces
WHERE is_default = 1;

SELECT DISTINCT
o.name,
o.OBJECT_ID,
o.create_date,
gt.NTUserName,
gt.HostName,
gt.SPID, (8*p.reserved_page_count)/1024.0 size_mb
FROM sys.fn_trace_gettable( @FileName, DEFAULT ) AS gt
JOIN tempdb.sys.objects AS o WITH (NOLOCK) ON gt.ObjectID = o.OBJECT_ID
INNER JOIN tempdb.sys.dm_db_partition_stats p WITH (NOLOCK) ON p.object_id = o.object_id AND p.index_id IN (0,1)
WHERE gt.DatabaseID = 2

Unable to shrink database log

June 10, 2019

Database was in simple mode, no transactions to be written.

Receiving the following errors after tatting about trying to shrink the log prior to a backup.

“Cannot shrink log file because total number of logical log files cannot be fewer than 2.”
“Cannot shrink log file because requested size is larger than the start of the last logical log file”

detach database, rename the transactioon log.

Attach the database, dont use the gui, script it from the gui and delete reference to the log.

A new log will be generated. Boom.