'A list of read to file / write to file keywords for SQL Server
We're migrating a SQL Server and as part of preparing for this we need to know about any file access it will be doing to paths that may not exist any more.
There is a large amount of T-SQL we would need to go through to search for any reads / writes to file paths. I'm thinking I could search all of our T-SQL for keywords that do those operations to find potential problems.
Two example keywords I can think of are
OPENROWSET
QUERYOUT
Is there any others?
Solution 1:[1]
You want a list of keywords that might be in code somewhere that hard-codes a defunct path? Well, the list is very long... bulk insert, xp_cmdshell, sys.dm_os_file_exists, sp_OACreate, xp_fileexist, create database, alter database, restore database, backup database, ... enumerating this and somehow being sure you got them all will be difficult. It will certainly be easier to find all of the hard-coded paths (assuming you know the list of paths that have been removed) than to find all the keywords that might be involved in referencing them.
If you have removed a mapped drive called X:\, for example, it is much easier to search all procedures / job steps / etc. for %X:\% than it is to find all the places where you use BULK INSERT and then check each one of those to see if they reference X:\.
In either case, I put together this handy search procedure that searches code for a specific string. You can certainly use it to find all instances of BULK INSERT, and all instances of xp_cmdshell, etc. But again it will be a lot easier to search for the explicit paths / drive letters / network shares, and even use that as an opportunity to change the way your code references paths that can change (e.g. put them in config or in a table, instead of hard-coding them anywhere).
CREATE PROCEDURE dbo.FindStringInModules
@search_string nvarchar(4000),
@database_list nvarchar(max) = NULL,
@case_sensitive bit = 0,
@search_jobs bit = 0,
@search_job_and_step_names bit = 0,
@search_schema_names bit = 0,
@search_object_names bit = 0,
@search_column_names bit = 0,
@search_parameter_names bit = 0,
@search_system_objects bit = 0,
@search_system_databases bit = 0,
@search_everything bit = 0,
@debug bit = 0
AS
BEGIN
SET NOCOUNT ON;
IF @search_everything = 1
BEGIN
SELECT
@search_jobs = 1,
@search_job_and_step_names = 1,
@search_object_names = 1,
@search_schema_names = 1,
@search_column_names = 1,
@search_parameter_names = 1,
@search_system_objects = 1,
@search_system_databases = 1;
END
DECLARE @sql nvarchar(max),
@template nvarchar(max),
@exec nvarchar(1024),
@all_text nvarchar(128),
@coll_text nvarchar(128);
SELECT @sql = N'',
@template = N'',
@all_text = CASE @search_system_objects
WHEN 1 THEN N'all_' ELSE N'' END,
@coll_text = CASE @case_sensitive
WHEN 1 THEN N'Latin1_General_100_CS_AS_SC'
WHEN 0 THEN N'Latin1_General_100_CI_AS_SC'
END;
CREATE TABLE #o
(
[database] nvarchar(130),
[schema] nvarchar(130),
[object] nvarchar(130),
[type] nvarchar(130),
create_date datetime,
modify_date datetime,
column_name nvarchar(130),
param_name nvarchar(130),
definition xml
);
SET @search_string = N'%' + @search_string + N'%';
SET @template = N'
SELECT [database] = DB_NAME(),
[schema] = s.name,
[object] = o.name,
[type] = o.type_desc,
o.create_date,
o.modify_date,
[column_name] = $col$,
[param_name] = $param$,
definition = CONVERT(xml, ''<?query -- '' + QUOTENAME(DB_NAME())
+ CHAR(13) + CHAR(10) + OBJECT_DEFINITION(o.object_id)
+ CHAR(13) + CHAR(10) + ''--'' + CHAR(63) + ''>'')
FROM sys.$all$objects AS o
INNER JOIN sys.schemas AS s
ON o.[schema_id] = s.[schema_id]';
SET @sql = @sql + REPLACE(REPLACE(@template, N'$col$', N'NULL'), N'$param$', N'NULL')
+ N'
' + N' WHERE OBJECT_DEFINITION(o.[object_id]) COLLATE $coll$
' + N' LIKE @s COLLATE $coll$';
SET @sql = @sql + CASE @search_schema_names WHEN 1 THEN N'
OR s.name COLLATE $coll$
LIKE @s COLLATE $coll$' ELSE N'' END;
SET @sql = @sql + CASE @search_object_names WHEN 1 THEN N'
OR o.name COLLATE $coll$
LIKE @s COLLATE $coll$' ELSE N'' END;
SET @sql = @sql + CASE @search_column_names WHEN 1 THEN N';
' + REPLACE(REPLACE(@template, N'$col$', N'c.name'),N'$param$',N'NULL')
+ N'
INNER JOIN sys.$all$columns AS c ON o.[object_id] = c.[object_id]
AND c.name COLLATE $coll$
LIKE @s COLLATE $coll$;' ELSE N'' END;
SET @sql = @sql + CASE @search_parameter_names WHEN 1 THEN N';
' + REPLACE(REPLACE(@template, N'$col$', N'NULL'),N'$param$',N'p.name')
+ N'
INNER JOIN sys.$all$parameters AS p ON o.[object_id] = p.[object_id]
AND p.name COLLATE $coll$
LIKE @s COLLATE $coll$;' ELSE N'' END;
SET @sql = REPLACE(REPLACE(@sql, N'$coll$', @coll_text), N'$all$', @all_text);
DECLARE @db sysname, @c cursor;
SET @c = cursor FORWARD_ONLY STATIC READ_ONLY FOR
SELECT QUOTENAME(name) FROM sys.databases AS d
LEFT OUTER JOIN dbo.fn_split(@database_list, N',') AS s ON 1 = 1
WHERE
(
LOWER(d.name) = LOWER(LTRIM(RTRIM(s.value)))
OR NULLIF(RTRIM(@database_list), N'') IS NULL
)
AND d.database_id >= CASE @search_system_databases
WHEN 1 THEN 1 ELSE 5 END
AND d.database_id < 32767
AND d.state = 0;
OPEN @c;
FETCH NEXT FROM @c INTO @db;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @exec = @db + N'.sys.sp_executesql';
IF @debug = 1
BEGIN
RAISERROR(N'Running dynamic SQL on %s:', 1, 0, @db);
PRINT @sql;
END
ELSE
BEGIN
INSERT #o
(
[database],
[schema],
[object],
[type],
create_date,
modify_date,
column_name,
param_name,
definition
)
EXEC @exec @sql, N'@s nvarchar(4000)', @s = @search_string;
END
FETCH NEXT FROM @c INTO @db;
END
IF @debug = 0
BEGIN
SELECT [database],
[schema],
[object],
[type],
create_date,
modify_date,
column_name,
param_name,
definition
FROM #o
ORDER BY [database], [schema], [object], [column_name], [param_name];
END
/* jobs */
IF @search_jobs = 1
BEGIN
SET @template = N'SELECT
job_name = j.name,
s.step_id,
s.step_name,
j.date_created,
j.date_modified,
[command_with_use] = CONVERT(xml, N''<?query -- ''
+ QUOTENAME(s.database_name)
+ CHAR(13) + CHAR(10) + s.[command]
+ CHAR(13) + CHAR(10) + ''--'' + CHAR(63) + ''>'')
FROM msdb.dbo.sysjobs AS j
INNER JOIN msdb.dbo.sysjobsteps AS s
ON j.job_id = s.job_id
WHERE s.command COLLATE $coll$
LIKE @s COLLATE $coll$'
+ CASE @search_job_and_step_names WHEN 1 THEN
N' OR j.name COLLATE $coll$
LIKE @s COLLATE $coll$
OR s.step_name COLLATE $coll$
LIKE @s COLLATE $coll$'
ELSE N'' END
+ N' ORDER BY j.name, s.step_id;';
SET @sql = REPLACE(@template, N'$coll$', @coll_text);
IF @debug = 1
BEGIN
PRINT N'Running this for jobs:';
PRINT @sql;
END
ELSE
BEGIN
EXEC sys.sp_executesql @sql, N'@s nvarchar(4000)', @s = @search_string;
END
END
END
GO
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Aaron Bertrand |
