Gerard's codebase
Over the years I have generated lots of little sub programs and stored away acres of useful code snippets. The problem is always to locate them.
Even more time wasting is forgetting how to do simple things when you havnt developed in an environment for a few years (or even a few months)
My new years resolution is to start putting them up in a common place as I produce them. (thanks google)
They are handy for me and, with a bit of a clean up and documentation, they might be handy for others if they wander in here.
Gerard 2008
Wednesday, November 4, 2015
Code for a View / Function comination to gernerate random numbers in tSQL
Here is a bit of a complex way of getting around this problem. Wrapping the RAND function in a view and calling via a UDF.
Modify as required but remember be careful of resource usage calling functions in select statement
CREATE VIEW vw_RandNumber_tempDEVOnly
AS
--gerard 28/10 this is a temporary setup to generate random data to allow me to develop a report in a system where we haven't put the required grouping data
SELECT RAND() as RandNumber
ALTER FUNCTION fRandNumber_tempDEVOnly(@Min int, @Max int)
RETURNS float
AS
--gerard 28/10 this is a temporary setup to generate random data to allow me to develop a report in a system where we haven't put the required grouping data
BEGIN
RETURN ROUND(@Min + (select RandNumber from vw_RandNumber_tempDEVOnly) * (@Max-@Min),0)
END
--call like this
SELECT dbo.fRandNumber_tempDEVOnly(1,3)
Sunday, July 12, 2015
SSRS get the run history and parameters used for individual report
/*
useful code for getting the run history and parameters used of a report
*/
DECLARE @ReportName AS VARCHAR(MAX)
SET @ReportName = '%Report1%'--report name hers surrounded by wildcards
SELECT * FROM
(
SELECT
InstanceName,
COALESCE(C.Path, 'Unknown') AS ItemPath,
UserName,
ExecutionId,
CASE(RequestType)
WHEN 0 THEN 'Interactive'
WHEN 1 THEN 'Subscription'
WHEN 2 THEN 'Refresh Cache'
ELSE 'Unknown'
END AS RequestType, -- SubscriptionId,
Format, Parameters,
CASE(ReportAction) WHEN 1 THEN 'Render'
WHEN 2 THEN 'BookmarkNavigation'
WHEN 3 THEN 'DocumentMapNavigation'
WHEN 4 THEN 'DrillThrough'
WHEN 5 THEN 'FindString'
WHEN 6 THEN 'GetDocumentMap'
WHEN 7 THEN 'Toggle'
WHEN 8 THEN 'Sort'
WHEN 9 THEN 'Execute'
ELSE 'Unknown'
END AS ItemAction,
TimeStart,
TimeEnd,
TimeDataRetrieval,
TimeProcessing,
TimeRendering,
CASE(Source)
WHEN 1 THEN 'Live'
WHEN 2 THEN 'Cache'
WHEN 3 THEN 'Snapshot' WHEN 4 THEN 'History'
WHEN 5 THEN 'AdHoc'
WHEN 6 THEN 'Session'
WHEN 7 THEN 'Rdce'
ELSE 'Unknown'
END AS Source,
Status,
ByteCount,
[RowCount],
AdditionalInfo
FROM ExecutionLogStorage EL WITH(NOLOCK)
LEFT OUTER JOIN Catalog C WITH(NOLOCK) ON (EL.ReportID = C.ItemID)
)AS a
WHERE ItemPath like @ReportName
Monday, July 6, 2015
Search and Locate report items the SSRS database (ie which reports did I use the SQL function i am modifying in etc)
Following code will list report objects in a Reporting Server Database. It can be modified to serarch for specific items in specific reports (ie which reports contain reference to a certain data set or paramater list etc)
--The first CTE gets the content as a varbinary(max)
--as well as the other important columns for all reports,
--data sources and shared datasets.
WITH ItemContentBinaries AS
(
SELECT
ItemID,Name,[Type]
,CASE Type
WHEN 2 THEN 'Report'
WHEN 5 THEN 'Data Source'
WHEN 7 THEN 'Report Part'
WHEN 8 THEN 'Shared Dataset'
ELSE 'Other'
END AS TypeDescription
,CONVERT(varbinary(max),Content) AS Content
FROM ReportServer.dbo.Catalog
WHERE Type IN (2,5,7,8)
),
--The second CTE strips off the BOM if it exists...
ItemContentNoBOM AS
(
SELECT
ItemID,Name,[Type],TypeDescription
,CASE
WHEN LEFT(Content,3) = 0xEFBBBF
THEN CONVERT(varbinary(max),SUBSTRING(Content,4,LEN(Content)))
ELSE
Content
END AS Content
FROM ItemContentBinaries
where Name like '%%' --add filter here
)
--The old outer query is now a CTE to get the content in its xml form only...
,ItemContentXML AS
(
SELECT
ItemID,Name,[Type],TypeDescription
,CONVERT(xml,Content) AS ContentXML
FROM ItemContentNoBOM
)
--now use the XML data type to extract the queries, and their command types and text....
SELECT
ItemID,Name,[Type],TypeDescription,ContentXML
,ISNULL(Query.value('(./*:CommandType/text())[1]','nvarchar(1024)'),'Query') AS CommandType
,Query.value('(./*:CommandText/text())[1]','nvarchar(max)') AS CommandText
FROM ItemContentXML
--Get all the Query elements (The "*:" ignores any xml namespaces)
CROSS APPLY ItemContentXML.ContentXML.nodes('//*:Query') Queries(Query)
Tuesday, June 21, 2011
SQL Server Db stuck in restore state
If the situation is that the database has fully restored but has not not recieved the recover command the following tSQL will put it back to an operational state
RESTORE DATABASE
Tuesday, April 14, 2009
List Object in SQL Db - Specific Examples
The following are more specific examples
-- This snippet searches for columns named like %product%
SELECT
o.name AS TableName,c.*
FROM
sysobjects AS o
INNER JOIN syscolumns AS c
ON c.id = o.id
WHERE
(o.type = 'U' OR o.type = 'S')
AND c.name LIKE '%product%'
Thursday, April 2, 2009
Deleting Restoring Databases
Tuesday, November 18, 2008
Avoid cursors in SQL Server with these methods to loop over records
Matthew Schroeder
11.17.2008
Rating: --- (out of 5)
Method 1: Temp table with identity column In the first approach, we will use a temp table with an identity column added to allow for row-by-row selection. If you're performing an INSERT/UPDATE/DELETE, be sure to use the explicit transactions. This vastly reduces the load on your log file by committing per loop, and it prevents huge rollbacks in the case of failure. set nocount on Always do this after the insert, since it's faster to add the index in bulk than to update the index as you write into the temp table. Since you know the data in this column, you can set the fill factor to 100% to get the best read times. */ Method 2: Temp table without ID In the second approach, we use a temp table without an identity column and simply grab the top row to process, then loop until we find no more rows to process. If you're performing an INSERT/UPDATE/DELETE, again, be sure to use the explicit transactions to vastly reduce the load on your log file by committing per loop, which prevents huge rollbacks in the case of failure. set nocount on Always do this after the insert, since it's faster to add the index in bulk than to update the index as you write into the temp table. Since you know the data in this column, you can set the fill factor to 100% to get the best read times. */ Method 3: Selecting a comma-delimited list of items When most developers/DBAs are asked to come up with a list of comma-delimited values from a table, they typically use a cursor or temp table (as above) to loop through the records. However, if you do not need to use a GROUP BY or an ORDER BY, then you can use the method below that operates in batch to handle the task. This cannot be used with GROUP BY DISTINCT, or ORDER BY, because of how SQL Server handles those operations. Basically, this takes a given variable, and for every row in the table it adds the current value to the variable along with a comma. declare @vrs varchar(4000) This article gives you some good reasons why cursors in SQL Server should be avoided as well as some alternatives that give you looping functionality. Keep in mind that SQL Server is designed around batch processing, so the less you loop, the faster your system will run. | ||||||||||||||
Thursday, October 23, 2008
Finding who is connected to a database and disconnecting them
select spid, status, loginame, hostname, blocked, db_name(dbid), cmd from master..sysprocesses where db_name(dbid) = 'database name'
--disconnect the user
kill 999 --where 999 is the spid from the above statement
Alternative
--list all users in a database - run against the db you are looking into
sp_who
--disconnect the user
kill vid
Tuesday, September 30, 2008
List objects in a SQL database
I mainly use it as the best way to search for occurance of fields in tables but can be modified in a multitude of ways. The sysobjects.xtype field is the key and I have listed its values below
pt.sql
-- C : CHECK constraint
-- D : Default or DEFAULT constraint
-- F : FOREIGN KEY constraint
-- L : Log
-- P : Stored procedure
-- PK : PRIMARY KEY constraint (type is K)
-- RF : Replication filter stored procedure
-- S : System tables
-- TR : Triggers
-- U : User table
-- UQ : UNIQUE constraint (type is K)
-- V : Views
-- X : Extended stored procedure
-- TF : Functions
USE master -- only an example - run local to the database you are searching
SELECT
o.name AS TableName,
o.type AS ObjectType,
c.name AS FieldName,
s.name AS FieldType,
c.prec,
c.scale,
c.isnullable
FROM
sysobjects AS o
INNER JOIN syscolumns AS c
ON c.id = o.id
INNER JOIN systypes AS s
ON c.xtype = s.xtype
WHERE
--select all user tables
o.type = 'U'
--other example select all user tables containing the field SalesPersonId
--o.type = 'U' and c.name = 'SalesPersonId'
Tuesday, September 23, 2008
Tip Using SQL Profiler - run as log then load into a table
The following tip is from the microsoft article http://msdn.microsoft.com/en-us/library/ms979207.aspx?ppud=4
Run the trace as a file then import into a table
SELECT * INTO trace1108 FROM ::fn_trace_gettable('C:\MyTrace.trc', default)
Setting filters in SQL Profiler is a pain in the bottom - expect to get it wrong and have to fiddle with your settings. Often it is better just to run what you can, load it into a table and run a few deletes to get rid of records that are known not to be needed
Sunday, July 27, 2008
SLQ 2000 Script to Maintain Indexes
The following script creates 2 tables and a stored procedure that can be run as a periodic job. It will defrag any indexes > 30% fragmentation in its default state.
Just be wary if you are log shipping though. Index work of any kind can blow out your log file size.
To install replace "Database Name Here" with your database name - open query analyzer and run the script.
The handling of the indexes can be controlled via the maint_index table. Be aware that the stored procedure processes the indexes in this table then repopulates it with the current state of the database. It is designed this way for a set and forget operation that will also allow you to make modifications to the indexes or force a rebuild by changing values in the maint_index table. This means in practice that if you are running it once per week then the indexes will be rebuilt bases on their state the previous week when the stored procedure was last run.
Fragmenting indexes will bubble up to the top and get processed but the maximum they will be processed is every second run.
Script Variables that can be set
- @db_name - self explanitory - this needs to be set
- @maxfrag - changes the fragmentation level at which an index is
- @maxminutes - This is a safety setting to limit how long the defrag process will run. If the script is still defraging after this period of time it will finish the current index and exit the loop
You can go to the maint_index table and change operation performed on individual indexes the next time the script is run.
- Force_Defrag_REINDEX By default the script runs a defrag on the index (0). If you set this to 1 then a full reindex will be performed (but be aware that the table might be offline during this operation)
- SetFillFactor This will change the fill factor of the index. the default is its existing value.
Enjoy
Gerard
CREATE TABLE [maint_index] (
[Id] [int] IDENTITY (1, 1) NOT NULL ,
[ObjectName] [char] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[IndexName] [char] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[LogicalFrag] [decimal](18, 0) NULL ,
[Force_Defrag_REINDEX_1or2] [int] NULL CONSTRAINT [DF_maint_index_Force_Defrag_REINEX] DEFAULT (0),
[SetFillFactor] [int] NULL CONSTRAINT [DF_maint_index_FillFactor] DEFAULT (0),
[ObjectId] [int] NULL ,
[IndexId] [int] NULL ,
[Lvl] [int] NULL ,
[CountPages] [int] NULL ,
[CountRows] [int] NULL ,
[MinRecSize] [int] NULL ,
[MaxRecSize] [int] NULL ,
[AvgRecSize] [int] NULL ,
[ForRecCount] [int] NULL ,
[Extents] [int] NULL ,
[ExtentSwitches] [int] NULL ,
[AvgFreeBytes] [int] NULL ,
[AvgPageDensity] [int] NULL ,
[ScanDensity] [decimal](18, 0) NULL ,
[BestCount] [int] NULL ,
[ActualCount] [int] NULL ,
[ExtentFrag] [decimal](18, 0) NULL ,
[Defrag] [int] NULL CONSTRAINT [DF_maint_index_Defrag] DEFAULT (0),
[Fill_Factor] [int] NULL CONSTRAINT [DF_maint_index_Fill_Factor] DEFAULT (0)
) ON [PRIMARY]
GO
CREATE PROCEDURE [dbo].[maint_index_process] AS
SET NOCOUNT ON
--maint_index
SET NOCOUNT ON
DECLARE @db_name VARCHAR (128)
DECLARE @tablename VARCHAR (128)
DECLARE @execstr VARCHAR (255)
DECLARE @indexname VARCHAR (255)
DECLARE @objectid INT
DECLARE @indexid INT
DECLARE @frag DECIMAL
DECLARE @reindex INT
DECLARE @fill INT
DECLARE @maxfrag DECIMAL
DECLARE @maxminutes INT
DECLARE @maxruntime DATETIME
DECLARE @TempId int
--specify for each database it is run on
SELECT @db_name = 'CMS'
--maximum fragmentation to allow
SELECT @maxfrag = 30.0
--maximum time for the process to run, it will exit the loop if this time is exceeded
--Note1 if reindex run over they will not be stopped
SELECT @maxminutes = 90--1.5 hours
select @maxruntime = DATEADD(minute,@maxminutes,GET
--process reindexes, marked defrags, defrags over @maxfrag
DECLARE indexes CURSOR FOR
SELECT ObjectName, ObjectId, IndexName, IndexId, LogicalFrag, Force_Defrag_REINDEX_1or2, SetFillFactor
FROM maint_index
WHERE indexid >0
AND IndexId <> 255 --this indicates image data and cannot be defragged
AND (LogicalFrag>=@maxfrag
OR Force_Defrag_REINDEX_1or2 > 0)
ORDER BY Force_Defrag_REINDEX_1or2 DESC --do the reindexing first, indexes specifed to be defragmented then general fragmented over @maxfrag
-- Open the cursor
OPEN indexes
-- loop through the indexes
FETCH NEXT
FROM indexes
INTO @tablename,@objectid, @indexname, @indexid, @frag, @reindex, @fill
WHILE (@@FETCH_STATUS = 0) AND (GETDATE()< @maxruntime)--while we still have records and we havn't exceeded out times
BEGIN
IF @reindex = 2
BEGIN
IF @fill<1
BEGIN
SELECT @execstr = '])'--go with the default fill factor
SELECT @fill = -1 --indicate in history table that existing fill was used
END
ELSE
BEGIN
SELECT @execstr = '],' + CAST(@fill AS VARCHAR) + ')'
END
--create the command and insert initial history record
SELECT @execstr = 'DBCC DBREINDEX (''[' + @db_name + '].dbo.[' + RTRIM(@tablename) + ']'',[' + RTRIM(@indexname) + @execstr
INSERT INTO maint_index_history (maint_Database,maint_Table,ma
VALUES (@db_name,RTRIM(@tablename),RT
SELECT @TempId=@@identity
--Do a reindex
EXEC (@execstr)
--update the history record
UPDATE maint_index_history SET EndTime= GETDATE() WHERE Id = @TempId
SELECT @TempId=0
END
ELSE
BEGIN
--create the command and insert initial history record
SELECT @execstr = 'DBCC INDEXDEFRAG ([' + @db_name + '], [' + RTRIM(@tablename) + '],[' + RTRIM(@indexname) + '])'
INSERT INTO maint_index_history (maint_Database,maint_Table,ma
VALUES (@db_name,RTRIM(@tablename),RT
SELECT @TempId=@@identity
--Do a Defrag
EXEC (@execstr)
--update the history record
UPDATE maint_index_history SET EndTime= GETDATE() WHERE Id = @TempId
SELECT @TempId=0
END
FETCH NEXT FROM indexes
INTO @tablename,@objectid, @indexname, @indexid, @frag, @reindex, @fill
END
-- Close and deallocate the cursor
CLOSE indexes
DEALLOCATE indexes
--create temporary table
-- Create the table
CREATE TABLE #fraglist (
ObjectName CHAR (255),
ObjectId INT,
IndexName CHAR (255),
IndexId INT,
Lvl INT,
CountPages INT,
CountRows INT,
MinRecSize INT,
MaxRecSize INT,
AvgRecSize INT,
ForRecCount INT,
Extents INT,
ExtentSwitches INT,
AvgFreeBytes INT,
AvgPageDensity INT,
ScanDensity DECIMAL,
BestCount INT,
ActualCount INT,
LogicalFrag DECIMAL,
ExtentFrag DECIMAL)
-- Declare cursor
DECLARE tables CURSOR FOR
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
-- Open the cursor
OPEN tables
-- Loop through all the tables in the database
FETCH NEXT
FROM tables
INTO @tablename
WHILE @@FETCH_STATUS = 0
BEGIN
-- Do the showcontig of all indexes of the table
INSERT INTO #fraglist
EXEC ('DBCC SHOWCONTIG (''' + @tablename + ''')
WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS')
FETCH NEXT
FROM tables
INTO @tablename
END
-- Close and deallocate the cursor
CLOSE tables
DEALLOCATE tables
--insert the temporary table into the maint_index then drop it
TRUNCATE TABLE maint_index--clear out existing data
INSERT INTO maint_index
(ObjectName,IndexName,LogicalF
select
ObjectName,IndexName,LogicalFr
from #fraglist
where indexid >0
DROP TABLE #fraglist
Remember that you need to uncheck the "delete backup and restore" checkbox