Archive for the 'TSQL' Category

Search all tables

Als je niet weet in welke tabel een bepaalde tekst string in een SQL database staat dan kan de volgende stored procedure je verder helpen.

Deze zoekt namelijk op basis van een zoek string parameter heel je database door op zoek naar deze string en toon in welke tabellen deze voorkomt.

Deze credits voor deze stored procedure gaan naar Narayana Vyas Kondreddi


CREATE PROC SearchAllTables
(
	@SearchStr nvarchar(100)
)
AS
BEGIN

	-- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved.
	-- Purpose: To search all columns of all tables for a given search string
	-- Written by: Narayana Vyas Kondreddi
	-- Site: http://vyaskn.tripod.com
	-- Tested on: SQL Server 7.0 and SQL Server 2000
	-- Date modified: 28th July 2002 22:50 GMT

	CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))

	SET NOCOUNT ON

	DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
	SET  @TableName = ''
	SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')

	WHILE @TableName IS NOT NULL
	BEGIN
		SET @ColumnName = ''
		SET @TableName =
		(
			SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
			FROM 	INFORMATION_SCHEMA.TABLES
			WHERE 		TABLE_TYPE = 'BASE TABLE'
				AND	QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
				AND	OBJECTPROPERTY(
						OBJECT_ID(
							QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
							 ), 'IsMSShipped'
						       ) = 0
		)

		WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
		BEGIN
			SET @ColumnName =
			(
				SELECT MIN(QUOTENAME(COLUMN_NAME))
				FROM 	INFORMATION_SCHEMA.COLUMNS
				WHERE 		TABLE_SCHEMA	= PARSENAME(@TableName, 2)
					AND	TABLE_NAME	= PARSENAME(@TableName, 1)
					AND	DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
					AND	QUOTENAME(COLUMN_NAME) > @ColumnName
			)

			IF @ColumnName IS NOT NULL
			BEGIN
				INSERT INTO #Results
				EXEC
				(
					'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630)
					FROM ' + @TableName + ' (NOLOCK) ' +
					' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
				)
			END
		END
	END

	SELECT ColumnName, ColumnValue FROM #Results
END

Search and Replace SQL Server 2005+

Zo eindelijk een search en replace functie gevonden voor SQL server 2005+ die geen tijdelijke tabellen en cursors gebruikt:


UPDATE TableName
SET DBTextField = REPLACE(CAST(DBTextField AS varchar(MAX)), 'SearchText', 'ReplaceText')
FROM TableName
WHERE CHARINDEX('SearchText',CAST(DBTextField as varchar(MAX)))>0 

‘A connection could not be made to the report server’

Deze fout wordt ontstaat wanneer er een verkeerde TargetServerURL in the Business Intelligence (BI) project is gezet van Reporting Services applicatie.

Controleer de  TargetServerURL in het property scherm van je BI project. Check dat deze URL verwijst naar de ReportServer virtual directory en niet naar de Reports virtual directory (wat vaak de oorzaak is van deze fout).

bijvoorbeeld http://Mijnserver/ReportServer$SQL2005DEV/ en niet http://Mijnserver/Reports$SQL2005DEV/

Invalid column name ‘DesktopHtml’

In het pre DNN 5 tijdperk, maakten veel mensen gebruik van de ’search and replace’ stored procedure van het  bi4ce forum. In  DNN 5 zijn er een aantal velden waarin de content wordt opgeslagen hernoemd (’DesktopHtml’ verandert in ‘Content’) waardoor deze stored procedure niet meer werkt.

Hieronder staat de aangepaste SP voor DNN 5:


CREATE Procedure Replace_Content(
@For as varchar(100),
@With as varchar(100))
AS
--* REPLACES TEXT IN THE DESKTOP HTML MATCHING THE FOR VARIABLE
--* SAMPLE: Replace_Content '/Portals/0/', ''

--* MAIN DECLARATION
DECLARE
@pointer binary(16),
@index INT,
@lenFor INT,
@lenWith INT,
@diff int,
@id INT,
@count INT

--* STANDARD RUNTIME VARIABLES
SET @lenFor = LEN(@For)
SET @diff = @lenFor - LEN(@With)

--* CREATE THE TEMPORARY TABLE
CREATE TABLE #Temporary
(
[id] int,     --MAPS TO YOUR SOURCE TABLE PKID
[oldtext] text, --ORIGINAL SOURCE TEXT (NOT REQUIRED)
[oldlength] int,--ORIGINAL SOURCE LENGTH
[text] text,     --NEW TEXT VALUE
[length] int,     --NEW LENGTH
[cLength] int    --CHECKSUM LENGTH
)

--* LOOP THROUGH THE SOURCE TABLE
--* IDENTIFY ALL RECORDS WHICH MATCH YOUR PATTERN
DECLARE irows CURSOR
LOCAL FORWARD_ONLY STATIC READ_ONLY FOR
SELECT moduleid
FROM HtmlText
WHERE PATINDEX('%'+@For+'%', Content)>0
OPEN irows

FETCH NEXT FROM irows INTO @id

WHILE (@@FETCH_STATUS = 0)
BEGIN
--* INSERT MATCHING RECORDS INTO THE TEMPORARY TABLE
INSERT INTO #Temporary(id, oldtext, oldlength, text)
SELECT
ModuleID,
Content,
datalength(Content),
Content from HtmlText
where ModuleID = @id

--* GRAB THE POINTER OF THE OBJECT TO BE USED FOR UPDATETEXT
SELECT
@pointer = TEXTPTR(text)
FROM #Temporary
WHERE id=@id
--* GET THE FIRST INDEX OF OUR PATTERN
SELECT
@index = PATINDEX('%'+@For+'%', text)
FROM #Temporary
WHERE id=@id

--* IF WE FOUND ANY ENTRIES, LOOP UNTIL WE REPLACE ALL OF THEM
IF @index > 0
BEGIN
select @count = 0
WHILE (
SELECT
PATINDEX('%'+@For+'%', text)
FROM #Temporary
WHERE id=@id
) > 0
BEGIN
--* KEEP A RUNNING TOTAL OF IDENTIFIED ENTRIES FOR LENGTH CHECKSUM
select @count = @count + 1
SELECT
@index = PATINDEX('%'+@For+'%', text)-1
FROM #Temporary
WHERE id=@id

--* UPDATE THE TEMPORARY VALUE
UPDATETEXT #Temporary.text @pointer @index @lenFor @With
END
--* UPDATE THE TEMPORARY RECORD, SET LENGTH AND CLENGTH VALUES FOR CHECKSUM
UPDATE #Temporary set
length=datalength(text),
cLength=datalength(oldtext) - @count * @diff
WHERE id=@id
END
FETCH NEXT FROM irows INTO @id
END

CLOSE irows
DEALLOCATE irows
--* UPDATE THE DATABASE FOR ALL RECORDS IN THE TEMPORARY
--* WHERE THE CHECKSUM LENGTH MATCHED THE RESULT LENGTH
UPDATE target set
target.Content = t.[text]
FROM
HtmlText target JOIN #Temporary t
ON
target.ModuleId = t.id AND
t.length = t.cLength

--* DELETE ALL RECORDS FROM TEMPORARY WHICH WERE SUCCESSFUL
DELETE from #Temporary where length=clength

--* RETURN ALL ROWS WHICH FAILED LENGTH COMPARISON
--* THIS SHOULD ALWAYS BE EMPTY
select * from #Temporary

--* DROP THE TEMP TABLE AND EXIT
DROP TABLE #Temporary

Dubbele rijen verwijderen

Het verwijderen van dubbele rijen is vaak een lastige taak. Met de onderstaande query is dit een stuk makkelijker, namelijk door eerst in een subselect query de unieke rijen op te halen via de GROUP BY kunnen vervolgens de overige rijen worden (die niet voorkomen in deze subselect ) worden verwijdert :


DELETE FROM eenTabel
WHERE 	IDcolumn NOT IN
	(SELECT MAX(IDcolumn)
	FROM eenTabel
	GROUP BY columnMetDubbeleWaarde, columnMetDubbeleWaarde, columnMetDubbeleWaarde)

Enable ‘Ad Hoc Distributed Queries’ for Sql Server 2005


sp_configure 'show advanced options',1
reconfigure with override
go
sp_configure 'Ad Hoc Distributed Queries',1
reconfigure with override
go

TSQL Query paging

Paginering in TSQL is wat lastiger dan bij MySQL waar er gebruik gemaakt kan worden van LIMI, TSQL mist deze opdracht maar hier is een workaround.

Zoeken in stored procedures


CREATE PROCEDURE [dbo].[sp_find_procs_containing]@search VARCHAR(100) = ” AS SET @search = ‘%’ + @search + ‘%’

SELECT ROUTINE_NAME, ROUTINE_DEFINITION

FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_DEFINITION LIKE @search ORDER BY ROUTINE_NAME

Optional filter parameters

To filter a table with one query you can do the following:


EmployeeID int
DepartmentID int
ManagerID int
LocationID int

Now assume you want users of your application to be able to find an Employee by specifying any of the criteria they so desire. User1 may just want to find all employees who Joe Manager [ManagerID: 5] manages, User2 may want to find all employees who Joe Manager manages, but only if they are in the Technology Department [DepartmentID: 49]. Using the technique I shared with my co-worker would result in a proc that looks like this:


CREATE PROCEDURE ap_SearchEmployee
(
@EmployeeID int = -1,
@DepartmentID int = -1,
@ManagerID int = -1,
@LocationID int = -1
)

as

SET NOCOUNT ON

SELECT * FROM Employee e
WHERE
(@EmployeeID = -1 OR e.EmployeeID = @EmployeeID)
AND (@DepartmentID = -1 OR e.DepartmentID = @DepartmentID)
AND (@ManagerID = -1 OR e.ManagerID = @ManagerID)
AND (@LocationID = -1 OR e.LocationID = @LocationID)

The where clause checks each parameter to see if it is -1 which means we don’t want to filter our results by that parameter. If the parameter is not -1 it then checks the fields value with that of the parameter. By using this technique my co-worker was able to remove the duplicate logic and nasty if/else blocks within his stored procedure which provided him with a much cleaner solution!

source