Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 GUID search query - performance

Author  Topic 

AskSQLTeam
Ask SQLTeam Question

0 Posts

Posted - 2004-11-15 : 07:57:44
Tyler writes "Hello,

I support an application that uses GUIDs all over in it's database. In order to troubleshoot application errors and to better understand relationships between the tables in the database I've written a query to search a database for a specified GUID. My problem is that I'm not a SQL expert and I'm sure the query is not optimal. I'm using a cursor :( as I have been unable to figure out any other way to get the data I want. Please have a look at my query below and let me know if you can figure out a way to not use the cursor as well as any other optimization suggestions you come up with.

Thanks,
Tyler


--Temporary table to hold Table and Column names that are related to GUID as well as the number of rows
CREATE TABLE #TablesWithGuid (Tablename varchar(255), ColName varchar(255), Rows int)

DECLARE @TableName varchar(255)
, @ColName varchar(255)
, @GUID varchar(40)
, @xtype int
, @SqlResult int
, @strSql nvarchar(4000)

--GUID that is being searched for.
SET @GUID = RTRIM(LTRIM('ENTER GUID HERE'))

--Drop outside characters if longer than 36. (Eg. { and } characters)
IF LEN(@GUID) = 38
BEGIN
SET @GUID = SUBSTRING(@GUID, 2, 36)
END


DECLARE GuidTableCol CURSOR FOR

-- Tables with a '%guid%' column name or Uniqueidentifier column. Column name as well.
SELECT DISTINCT CAST(so.[name] AS varchar(255)) AS [Table Name],
CAST(co.[name] AS varchar(255)) AS [Guid Column],
co.[xtype]

FROM sysobjects so INNER JOIN
(SELECT [name], [id], [xtype]
FROM syscolumns
WHERE (lower([name]) LIKE '%guid%') OR ([xtype] = 36)) co
ON co.[id] = so.[id]

WHERE (so.[xtype] = 'U') --Only User Tables

OPEN GuidTableCol
FETCH NEXT FROM GuidTableCol INTO @TableName, @ColName, @xtype
WHILE @@FETCH_STATUS = 0
BEGIN
/* Find which tables and columns have a matching Guid to the one we are searching for.
Return COUNT of matching rows as well. */
SET @SqlResult = 0

--change guid string to have brackets for cases when the column is a varchar or nvarchar
IF @xtype IN (167,231)
BEGIN
SET @GUID = '{' + @GUID + '}'
END

SET @strSql = 'SELECT @Result = COUNT(CAST([' + @ColName + '] AS varchar(255)))
FROM [' + @TableName + ']
WHERE CAST([' + @ColName + '] AS varchar(255)) = ''' + @GUID + ''''

/* @ColName is CAST as a varchar type since the COUNT function will not work on
uniqueidentifier types.

Since the @ColName is cast as a varchar, brackets {} cannot be used in the @GUID
string if the column is a uniqueidentifier. Otherwise the uniqueidentifier columns will
not match up with the @GUID string. */

EXECUTE sp_executesql @strSql, N'@Result int out', @SqlResult out

IF @SqlResult > 0 --If the result count is > 0 then add table, column, and count to #TablesWithGuid
BEGIN
INSERT INTO #TablesWithGuid VALUES (@TableName, @ColName, @SqlResult)
END

IF @xtype IN (167,231) --reset guid string if column is varchar or nvarchar
BEGIN
SET @GUID = SUBSTRING(@GUID, 2, 36)
END

FETCH NEXT FROM GuidTableCol INTO @TableName, @ColName, @xtype
END

CLOSE GuidTableCol
DEALLOCATE GuidTableCol

SELECT * FROM #TablesWithGuid

DROP TABLE #TablesWithGuid"

tkeith
Starting Member

9 Posts

Posted - 2004-12-02 : 12:57:25
With the help of the How to Perform SQL Server Row-by-Row Operations Without Cursors article on sql-server-performance.com I was able to use a loop instead of my cursor. I also made a few other changes based on some recommendations of a friend.

-Tyler

Here's my new query:


/* Temporary table to hold all columns that have a GUID name or uniqueidentifier type.
Holds an ID value (for looping), the table name and the column type as well. */

DECLARE @TablesToBeSearched TABLE(RowId smallint IDENTITY(1,1)
, TableName varchar(255)
, ColName varchar(128)
, ColType varchar(128))

--Temporary table to hold Table and Column names that are related to GUID
DECLARE @TablesWithGuid TABLE(TableName varchar(255), ColName varchar(128), RowsFound int)

DECLARE @TableName varchar(255)
, @ColName varchar(255)
, @GUID varchar(40)
, @ColType varchar(128)
, @SqlResult int
, @strSql nvarchar(4000)
, @currentrow smallint
, @nextrow smallint
, @loopcontrol smallint


--GUID that is being searched for.
SET @GUID = RTRIM(LTRIM('ENTER GUID HERE'))

--Drop { and } characters if present. Return if invalid guid entered.
IF LEN(@GUID) = 38 AND CHARINDEX('{',@GUID,1) = 1 AND CHARINDEX('}',@GUID,1) = 38
BEGIN
SET @GUID = SUBSTRING(@GUID, 2, 36)
END
ELSE IF LEN(@GUID) <> 36
BEGIN
SELECT 'Invalid Guid Specified' AS [ERROR]
RETURN
END

-- Get meta data for columns and tables that are GUIDs
INSERT INTO @TablesToBeSearched
SELECT isc.[TABLE_NAME]
, isc.[COLUMN_NAME]
, isc.[DATA_TYPE]
FROM INFORMATION_SCHEMA.[Columns] isc INNER JOIN INFORMATION_SCHEMA.Tables ist
ON isc.[TABLE_NAME] = ist.[TABLE_NAME]
WHERE ((LOWER(isc.[Column_Name]) LIKE '%guid%'
AND isc.[Data_Type] IN ('char','varchar','nchar','nvarchar')
AND COL_LENGTH((isc.[TABLE_NAME]),isc.[COLUMN_NAME]) > 35)
OR isc.[Data_Type] = 'uniqueidentifier')
AND ist.[TABLE_TYPE] = 'BASE TABLE'

--Initialize loop variables
SELECT @loopcontrol = 1
SELECT @nextrow = MIN(RowId)
FROM @TablesToBeSearched

--Make sure table has data
IF ISNULL(@nextrow,0) = 0
BEGIN
SELECT 'No Guid columns found in the ' + DB_NAME() + ' database' AS [ERROR]
RETURN
END

-- Retrieve the first row

SELECT @currentrow = [RowId]
, @TableName = [TableName]
, @ColName = [ColName]
, @ColType = [ColType]

FROM @TablesToBeSearched

WHERE RowId = @nextrow


WHILE @loopcontrol = 1
BEGIN
/* Find which tables and columns have a matching Guid to the one we are searching for.
Return COUNT of matching rows as well. */
SET @SqlResult = 0

--change guid string to have brackets for cases when the column is a varchar or nvarchar
IF @ColType IN ('char','varchar','nchar','nvarchar')
BEGIN
SET @GUID = '{' + @GUID + '}'
END

SET @strSql = 'SELECT @Result = COUNT(CAST([' + @ColName + '] AS varchar(255)))
FROM [' + @TableName + ']
WHERE CAST([' + @ColName + '] AS varchar(255)) = ''' + @GUID + ''''

/* @ColName is CAST as a varchar type since the COUNT function will not work on
uniqueidentifier types.

Since the @ColName is cast as a varchar, brackets {} cannot be used in the @GUID
string if the column is a uniqueidentifier. Otherwise the uniqueidentifier rows will
not match up with the @GUID string. */

EXECUTE sp_executesql @strSql, N'@Result int out', @SqlResult out

--If the result count is > 0 then add table, column, and count to @TablesWithGuid
IF @SqlResult > 0
BEGIN
INSERT INTO @TablesWithGuid VALUES (@TableName, @ColName, @SqlResult)
END

--reset guid string if column is not a uniqueidentifier
IF @ColType IN ('char','varchar','nchar','nvarchar')
BEGIN
SET @GUID = SUBSTRING(@GUID, 2, 36)
END

-- Reset looping variables.
SELECT @nextrow = NULL

-- get the next RowId
SELECT @nextrow = MIN(RowId)
FROM @TablesToBeSearched
WHERE [RowId] > @currentrow

-- did we get a valid next row id?
IF ISNULL(@nextrow,0) = 0
BEGIN
BREAK
END

-- get the next row.
SELECT @currentrow = [RowId]
, @TableName = [TableName]
, @ColName = [ColName]
, @ColType = [ColType]
FROM @TablesToBeSearched
WHERE RowId = @nextrow
END

SELECT * FROM @TablesWithGuid ORDER BY TableName, ColName
Go to Top of Page

Bustaz Kool
Master Smack Fu Yak Hacker

1834 Posts

Posted - 2004-12-05 : 09:01:56
Why are you storing a GUID in a char, varchar, nvarchar or nchar column?


HTH

=========================================
Let X = {All sets s such that s is not an element of s}

(X element of X) ==> (X not element of X)
(X not element of X) ==> (X element of X)

(Bertrand Russell Paradox)
Go to Top of Page

tkeith
Starting Member

9 Posts

Posted - 2004-12-07 : 14:19:11
Good question, I didn't write the application though, and I wasn't involved in designing the database so I really don't know. I just get to support the application. I found there were a few columns where Guids were stored as a varchar or nvarchar. The only thing that helped me identify them as a guid was that 'guid' was part of the column name. So I just expanded the search to include char, nchar, varchar, and nvarchar columns with a name LIKE '%guid%'.

-TK
Go to Top of Page
   

- Advertisement -