I wrote this query for searching a string in whole database . Earlier it was working properly now it doesn't fetch full result at all . I don't get what is wrong with this query . Please help
QUERY
/*
- Search through tables to find specific text
- Written by Luis Chiriff (with help from SQL Server Central)
- luis.chiriff#gmail.com # 24/11/2008 # 11:54
*/
-- Variable Declaration
Declare #StringToFind VARCHAR(200), #Schema sysname, #Table sysname, #FullTable int, #NewMinID
int, #NewMaxID int,
#SQLCommand VARCHAR(8000), #BaseSQLCommand varchar(8000), #Where VARCHAR(8000), #CountCheck
varchar(8000) , #FieldTypes varchar(8000),
#cursor VARCHAR(8000), #columnName sysname, #SCn int, #SCm int
Declare #TableList table (Id int identity(1,1) not null, tablename varchar(250))
Declare #SQLCmds table (id int identity(1,1) not null, sqlcmd varchar(8000))
Declare #DataFoundInTables table (id int identity(1,1) not null, sqlcmd varchar(8000))
-- Settings
SET #StringToFind = 'abcdef'
SET NOCOUNT ON
SET #StringToFind = '%'+#StringToFind+'%'
-- Gathering Info
if ((select count(*) from sysobjects where name = 'tempcount') > 0)
drop table tempcount
create table tempcount (rowsfound int)
insert into tempcount select 0
-- This section here is to accomodate the user defined datatypes, if they have
-- a SQL Collation then they are assumed to have text in them.
SET #FieldTypes = ''
select #FieldTypes = #FieldTypes + '''' + rtrim(ltrim(name))+''',' from systypes where collation
is not null or xtype = 36
select #FieldTypes = left(#FieldTypes,(len(#FieldTypes)-1))
insert into #TableList (tablename)
select name from sysobjects
where xtype = 'U' and name not like 'dtproperties'
order by name
-- Start Processing Table List
select #NewMinID = min(id), #NewMaxID = max(id) from #TableList
while(#NewMinID <= #NewMaxID)
Begin
SELECT #Table = tablename, #Schema='dbo', #Where = '' from #TableList where id = #NewMinID
SET #SQLCommand = 'SELECT * FROM ' + #Table + ' WHERE'
-- removed ' + #Schema + '.
SET #cursor = 'DECLARE col_cursor CURSOR FOR SELECT COLUMN_NAME
FROM [' + DB_NAME() + '].INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = ''' + #Schema + '''
AND TABLE_NAME = ''' + #Table + '''
AND DATA_TYPE IN ('+#FieldTypes+')'
--Original Check, however the above implements user defined data types --AND DATA_TYPE IN
(''char'',''nchar'',''ntext'',''nvarchar'',''text'',''varchar'')'
EXEC (#cursor)
SET #FullTable = 0
DELETE FROM #SQLCmds
OPEN col_cursor
FETCH NEXT FROM col_cursor INTO #columnName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #Where = #Where + ' [' + #columnName + '] LIKE ''' + #StringToFind + ''''
SET #Where = #Where + ' OR'
--PRINT #Table + '|'+ cast(len(isnull(#Where,''))+len(isnull(#SQLCommand,'')) as varchar(10))+'|'+#Where
if (len(isnull(#Where,''))+len(isnull(#SQLCommand,'')) > 3600)
Begin
SELECT #Where = substring(#Where,1,len(#Where)-3)
insert into #SQLCmds (sqlcmd) select #Where
SET #Where = ''
End
FETCH NEXT FROM col_cursor INTO #columnName
END
CLOSE col_cursor
DEALLOCATE col_cursor
if (#Where <> '')
Begin
SELECT #Where = substring(#Where,1,len(#Where)-3)
insert into #SQLCmds (sqlcmd)
select #Where --select #Table,count(*) from #SQLCmds
End
SET #BaseSQLCommand = #SQLCommand
select #SCn = min(id), #SCm = max(id) from #SQLCmds
while(#SCn <= #SCm)
Begin
select #Where = sqlcmd from #SQLCmds where ID = #SCn
if (#Where <> '')
Begin
SET #SQLCommand = #BaseSQLCommand + #Where
SELECT #CountCheck = 'update tempcount set rowsfound = (select count(*) '+ substring(#SQLCommand,10,len(#SQLCommand)) + ')'
EXEC (#CountCheck)
if ((select rowsfound from tempcount) > 0)
Begin
PRINT '--- ['+cast(#NewMinID as varchar(15))+'/'+cast(#NewMaxID as varchar(15))+'] '+#Table + ' ----------------------------------[FOUND!]'
--PRINT '--- [FOUND USING:] ' +#SQLCommand
insert into #DataFoundInTables (sqlcmd) select #SQLCommand
EXEC (#SQLCommand)
update tempcount set rowsfound = 0
End
else
Begin
PRINT '--- ['+cast(#NewMinID as varchar(15))+'/'+cast(#NewMaxID as varchar(15))+'] '+#Table
End
End
SET #SCn = #SCn + 1
End
set #NewMinID = #NewMinID + 1
end
if ((select count(*) from sysobjects where name = 'tempcount') > 0)
drop table tempcount
/*
This will now return all the sql commands you need to use
*/
select #NewMinID = min(id), #NewMaxID = max(id) from #DataFoundInTables
if (#NewMaxID > 0)
Begin
PRINT ' '
PRINT ' '
PRINT '-----------------------------------------'
PRINT '----------- TABLES WITH DATA ------------'
PRINT '-----------------------------------------'
PRINT ' '
PRINT 'We found ' + cast(#NewMaxID as varchar(10)) + ' table(s) with the string '+#StringToFind
PRINT ' '
while(#NewMinID <= #NewMaxID)
Begin
select #SQLCommand = sqlcmd from #DataFoundInTables where ID = #NewMinID
PRINT #SQLCommand
SET #NewMinID = #NewMinID + 1
End
PRINT ' '
PRINT '-----------------------------------------'
End
This query was working fine one month ago but now it doesn't fetch the results . Can anyone tell me what is wrong in this query .
Related
I have two databases in SQL Server 2014 Express, since a few days ago I am unifying both databases in such a way that there is only one left.
When I have this new database I must pass it to Azure (I don't have any experience using this technology), however, I am doing tests on my local server, so far I have created the whole scheme but I must fill out all the tables to perform tests with my application.
There are 313 tables of which many have more than 200,000 records, my question is, what is the best way to populate the database?
Because at this moment I want to test my local machine, I could fill in the tables through Tasks> Generate Script> Advanced Options (Include only data) but this information will change the day when the migration to Azure is done, therefore I must Do the same process.
So, is it possible to create an INSERT SELECT script so that it does not include records one by one and is as dynamic as possible? For example, you would have to generate an INSERT INTO similar to this:
SET IDENTITY_INSERT [SchemaX].[TableA] ON ;
INSERT INTO [SchemaX].[TableA]
(
[id]
,[fieldA]
,[fieldB]
,[fieldC])
SELECT
[id]
,[fieldA]
,[fieldB]
,[fieldC]
FROM [server].[dbname].[SchemaX].[TableA]
SET IDENTITY_INSERT [SchemaX].[TableA] OFF ;
Some tables have IDENTITY enabled so you would have to recognize which tables are like this and use SET IDENTITY_INSERT when inserting. This way you would have to link the production server and insert the information into the local server.
If there are suggestions or recommendations about another way you are welcome
Has been answered before ...
/****** Object: StoredProcedure [dbo].[procUtils_GenerateInsertProc] Script Date: 03/20/2010 13:06:13 ******/
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[procUtils_GenerateInsertProc]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[procUtils_GenerateInsertProc]
GO
/****** Object: StoredProcedure [dbo].[procUtils_GenerateInsertProc] Script Date: 03/20/2010 13:06:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--exec procUtils_GenerateInsertProc 'Whatever'
--exec sp_HelpText procUtils_GenerateInsertProc
CREATE PROCEDURE [dbo].[procUtils_GenerateInsertProc]
#TableName [varchar](50)
WITH EXECUTE AS CALLER
AS
BEGIN -- proc start
SET NOCOUNT ON;
BEGIN TRY --begin try
--FIRST SEARCH THE TABLE WHICH HAD A "Feature" in its name
--SELECT NAME FROM SYS.TABLES WHERE NAME LIKE '%Feature%'
--SELECT column_name from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='Feature' --SELECT * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='Task'
--Decalre a variable to remember the position of the current delimiter
DECLARE #ProcName varchar(1000)
set #ProcName = '[dbo].[procGen_' + #TableName + '_Insert]'
DECLARE #CurrentDelimiterPositionVar INT
DECLARE #PkColumnName varchar(200)
--Decalre a variable to remember the number of rows in the table
DECLARE #Count INT
DECLARE #ColumnName varchar(300);
DECLARE #DataType varchar(50)
DECLARE #IsNullable bit
DECLARE #MaxLength INT
DECLARE #IsComputed BIT
set #IsComputed = 0
DECLARE #IsPrimaryKey BIT
set #IsPrimaryKey = 0
DECLARE #CODESTR VARCHAR(max)
--PRINT DROP PROCEDURE
set #CODESTR = ' '
--Declare the Table variable
DECLARE #ColumnNames TABLE
(
Number INT IDENTITY(1,1), --Auto incrementing Identity column
TableName varchar(300) , --the name of the table
ColumnName VARCHAR(300) , --The string value ,
DataType varchar(50) , --the datatype
IsNullable bit , --should we add =null in front
MaxLength INT , --VARCHAR(LENGHTi)
IsComputed bit , --whether or not this table is computed
IsPrimaryKey bit --whether or not this table is computed
)
--Populate the TABLE variable using some logic
-- SELECT * from INFORMATION_SCHEMA.COLUMNS
INSERT INTO #ColumnNames
(
TableName ,
ColumnName ,
DataType ,
IsNullable ,
MaxLength ,
IsComputed ,
IsPrimaryKey )
SELECT
TableName ,
ColumnName ,
DataType ,
IsNullable ,
MaxLength ,
IsComputed ,
IsPrimaryKey
from viewMeta_TableColumns
--debug where TableName = 'Whatever'
where TableName = #TableName
--SELECT column_name , Data_type , IsNullable , MaxLength
--from INFORMATION_SCHEMA.COLUMNS
--where TABLE_NAME=#TableName
--Initialize the looper variable
SET #CurrentDelimiterPositionVar = 1
--Determine the number of rows in the Table
SELECT #Count=max(Number) from #ColumnNames
--A variable to hold the currently selected value from the table
set #CODESTR = #CODESTR + 'IF OBJECT_ID(''' + #ProcName + ''') IS NOT NULL
BEGIN
DROP PROC ' + #ProcName + '
END
GO'
set #CODESTR = #CODESTR + '
/****** Object: StoredProcedure ' + #ProcName + '*/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE ' + #ProcName + '
#CurUserSessionId [int] ,
#CurPageTypeId [int] ,
#MsgOut [varchar](200) OUTPUT ,
#DebugMsgOut [varchar](200) OUTPUT,
#Ret [int] OUTPUT ,' + CHAR(13)
--#COLUMN_NAME [DATA_TYPE] (MAX_LENGTH) =NULL ,
WHILE #CurrentDelimiterPositionVar <= #Count --1st loop
BEGIN
--Load current value from the Table
SELECT #ColumnName = ColumnName FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #DataType = DataType FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #MaxLength = MaxLength FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
set #IsNullable = ( select IsNullable FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
set #IsPrimaryKey = ( select IsPrimaryKey FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
if ( #DataType = 'timestamp' or #IsComputed = 1)
begin
set #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1
continue
end
set #CODESTR = #CODESTR + '#' + #ColumnName + ' ['+ #DataType + '] '
--ADD THE (200)
IF #MaxLength IS NOT NULL
BEGIN --IF #MaxLength IS NOT NULL
--xml
if #DataType <> 'xml' and #DataType <> 'sql_variant' and
#DataType <> 'text' and #DataType <> 'ntext' and #DataType <> 'image' and
#DataType <> 'hierarchyid' and #DataType <> 'bit' and #DataType <> 'varbinary' and
#DataType <> 'int' and #DataType <> 'uniqueidentifier' and #DataType <> 'tinyint' and
#DataType <> 'timestamp' and #DataType <> 'uniqueidentifier' and #DataType <> 'smallint' and
#DataType <> 'bigint' and #DataType <> 'smallmoney' and #DataType <> 'money' and
#DataType <> 'real' and #DataType <> 'smalldatetime' and #DataType <> 'datetime'
begin --those with()
if #MaxLength <> -1
SET #CODESTR = #CODESTR + '(' + CONVERT(VARCHAR , #MaxLength ) + ')'
else
SET #CODESTR = #CODESTR + '(max)'
end --those with(200)
else
begin
SET #CODESTR = #CODESTR --DO NOTHING
end
END --IF #MaxLength IS NOT NULL
IF #IsNullable = 1
SET #CODESTR = + #CODESTR + ' = NULL '
if #IsPrimaryKey = 1
SET #CODESTR = #CODESTR + ' OUTPUT '
if #CurrentDelimiterPositionVar <> #Count
SET #CODESTR = #CODESTR + ','
--DEBUGGING
--set #CODESTR = #CODESTR + '#ColumnName - ' + #ColumnName
--set #CODESTR = #CODESTR + '#DataType - ' + #DataType
--set #CODESTR = #CODESTR + '#IsNullable - ' + #IsNullable
--set #CODESTR = #CODESTR + '#MaxLength - ' + CONVERT ( VARCHAR , #MaxLength )
set #CODESTR = #CODESTR + CHAR(13)
SET #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1
END
SET #CODESTR = #CODESTR + '
WITH EXECUTE AS CALLER
AS
BEGIN -- proc start
SET NOCOUNT ON;
BEGIN TRY --begin try
--
set #Ret = 1 --assume false from the beginning
declare #MsgKey [nvarchar](max)
declare #MsgTxt [nvarchar](max)
exec procUtils_GetMsgTxtByKeyAndUserSessionId
#UserSessionId =2 ,
#MsgKey = ''MsgOkTheAddingOfItemIsOk'' ,
#MsgTxt = ''''
set #MsgOut = replace (#MsgTxt , ''{0}'' , ''' + #TableName + ''' )
declare #thisProcName varchar(300)
set #thisProcName= ( SELECT OBJECT_NAME(##PROCID))
'
SET #CurrentDelimiterPositionVar = 1 --START LOOP AGAIN
set #CODESTR = #CODESTR + '
--Action !!!
INSERT INTO [dbo].[' + #TableName + ']( ' + CHAR(13)
--Loop through until all row processing is done
WHILE #CurrentDelimiterPositionVar <= #Count --2nd loop
BEGIN
--Load current value from the Table
SELECT #ColumnName = ColumnName FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #DataType = DataType FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #MaxLength = MaxLength FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
set #IsNullable = ( select IsNullable FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
set #IsPrimaryKey = ( select IsPrimaryKey FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
if #IsPrimaryKey = 1
begin -- the primary key
set #PkColumnName = #ColumnName
end --the primary key
if ( #DataType = 'timestamp' or #IsComputed = 1 or #IsPrimaryKey = 1 )
begin
set #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1
continue
end
--select
if #CurrentDelimiterPositionVar <= #Count
BEGIN
set #CODESTR = #CODESTR + '[' + #ColumnName + ']' --null the codestring var
if #CurrentDelimiterPositionVar <> #Count
set #CODESTR = #CODESTR + ', --type of ' + #DataType + CHAR(13) --WITH COMMA
ELSE
set #CODESTR = #CODESTR + ' --type of ' + #DataType + CHAR(13) --NO COMMA
END -- IF SHOULD PRINT COLUMN
SET #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1;
END --eof while 2
set #CODESTR = #CODESTR + ') VALUES ( '
--AND START ALL OVER AGAIN
SET #CurrentDelimiterPositionVar = 1
--Loop through until all row processing is done
WHILE #CurrentDelimiterPositionVar <= #Count --WHILE 3
BEGIN
--Load current value from the Table
SELECT #ColumnName = ColumnName FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #DataType = DataType FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
SELECT #MaxLength = MaxLength FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar
set #IsNullable = ( select IsNullable FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
set #IsPrimaryKey = ( select IsPrimaryKey FROM #ColumnNames
WHERE Number = #CurrentDelimiterPositionVar )
if ( #DataType = 'timestamp' or #IsComputed = 1 or #IsPrimaryKey = 1)
begin
set #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1
continue
end
set #CODESTR = #CODESTR + '#' + #ColumnName
if #CurrentDelimiterPositionVar <= #Count
BEGIN
IF #CurrentDelimiterPositionVar <> #Count
set #CODESTR = #CODESTR + ' , --type of ' + #DataType --all others with comma
else
set #CODESTR = #CODESTR + ' --type of ' + #DataType --the last one without comma
END -- IF SHOULD NOT PRINT COLUMN
--increase the counter
set #CODESTR = #CODESTR + CHAR(13)
SET #CurrentDelimiterPositionVar = #CurrentDelimiterPositionVar + 1;
END
set nocount off
SET #CODESTR = #CODESTR + ')
SET #' + #pkColumnName + ' = ##IDENTITY
set #Ret = ##ERROR
set #DebugMsgOut = ''TODO:REMOVE INSERT OK ''
END TRY
BEGIN CATCH
EXEC #ret = [dbo].[procUtils_GetMsgTxtByKeyAndUserSessionId]
#UserSessionId = 2,
#MsgKey = N''ErrorMsgMenuRetrievalFailed'',
#MsgTxt = #MsgOut OUTPUT
set #ret = 1
set #msgOut = #MsgTxt
set #debugMsgOut = '' Error number: '' + CAST(ERROR_NUMBER() AS varchar(100)) +
''Error message: '' + ERROR_MESSAGE() + ''Error severity: '' +
CAST(ERROR_SEVERITY() AS varchar(10)) +
''Error state: '' + CAST(ERROR_STATE() AS varchar(100)) +
''XACT_STATE: '' + CAST(XACT_STATE() AS varchar(100))
-- record the error in the database
set #debugMsgOut = #debugMsgOut + #msgOut
INSERT INTO [dbo].[LogStore] ( [Date],[Thread],[Level],[Logger],[Message])
values ( getdate() , N''8'', N''DEBUG'', #thisProcName , #debugMsgOut )
END CATCH
END --procedure end
GO
'
print #codestr
END TRY --end try
BEGIN CATCH
print ' Error number: ' + CAST(ERROR_NUMBER() AS varchar(100)) +
'Error message: ' + ERROR_MESSAGE() + 'Error severity: ' +
CAST(ERROR_SEVERITY() AS varchar(1000)) +
'Error state: ' + CAST(ERROR_STATE() AS varchar(100)) +
'XACT_STATE: ' + CAST(XACT_STATE() AS varchar(100))
END CATCH
END --procedure end
--USE [Gaf]
--GO
--SELECT NAME FROM SYS.tables where name like '%Msg%'
--EXEC [dbo].[procUtils_GenerateInsertProc] #TableName = N'Whatever'
GO
I use dynamic sql with parameters and have problem :)
In block of code it works, but when I call procedure I have error that I need to declare scalar variable #name_dummy
So:
DECLARE #START_TIME DATETIME = GETDATE()
DECLARE #TMP_NAMES TABLE (
SCHEMA_N VARCHAR(500),
TABLE_N VARCHAR(500),
CONDITION VARCHAR(MAX),
TARGETDB VARCHAR(500),
SOURCEDB VARCHAR(500),
COLUMN_LIST VARCHAR(MAX)
)
DECLARE #SCHEMA_N VARCHAR(500)
DECLARE #TABLE_N VARCHAR(500)
DECLARE #CONDITION VARCHAR(MAX)
DECLARE #COLUMN_LIST VARCHAR(MAX)
DECLARE #TARGETDB VARCHAR(500)
DECLARE #SOURCEDB VARCHAR(500)
INSERT INTO #TMP_NAMES
SELECT
o.SCHEMA_N
,o.TABLE_N
,o.Condition
,o.TargetDB
,o.SourceDB
,STUFF((SELECT
', ' + c.name
FROM sys.columns c
WHERE c.object_id = o.object_id
AND c.system_type_id <> 189 /* Pomijam timestamp*/
ORDER BY c.column_id
FOR XML PATH (''))
, 1, 1, '')
FROM Table_A o
ORDER BY 1,
2
SELECT
SCHEMA_N
,TABLE_N
,CONDITION
,TARGETDB
,SOURCEDB
,COLUMN_LIST
FROM #TMP_NAMES
DECLARE KUR CURSOR
FOR
SELECT
SCHEMA_N
,TABLE_N
,CONDITION
,TARGETDB
,SOURCEDB
,COLUMN_LIST
FROM #TMP_NAMES
OPEN KUR
FETCH NEXT
FROM KUR
INTO #SCHEMA_N,
#TABLE_N,
#CONDITION,
#TARGETDB,
#SOURCEDB,
#COLUMN_LIST
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #TOP VARCHAR(100)
SET #TOP = ( SELECT CAST(Wartosc AS VARCHAR) FROM Table_B WHERE Id = 3 )
IF #TOP < 40000
SET #TOP = 40000
WHILE ( 1 = 1 )
BEGIN
DECLARE #CHECK BIT = 0
DECLARE #sqlCMD NVARCHAR(MAX) = 'SELECT TOP 1 #check_exists = 1 FROM '
+ #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' WHERE ' + #CONDITION
exec sp_executesql #sqlCMD, N'#check_exists bit OUTPUT, #START_TIME DATE', #check_exists = #CHECK OUTPUT, #START_TIME = #START_TIME;
SELECT #sqlCMD , #CHECK
END
END
FETCH NEXT
FROM KUR
INTO #SCHEMA_N,
#TABLE_N,
#CONDITION,
#TARGETDB,
#SOURCEDB,
#COLUMN_LIST
CLOSE KUR;
DEALLOCATE KUR
And when I execute this it's compiling and works ( returns values ) for example sql which I want to execute.
SELECT TOP 1 #check_exists = 1 FROM MSSF15_WarstwaPosrednia.KatalogZdarzen.MSSF_RaportZdarzenPLKB2CS2K WHERE StatusPrzetwarzania = 4 AND DataWpisu < DATEADD(MONTH, -3, #START_TIME)
Parameters work here ( #check_exists which is output and #START_TIME condition param ) , but when I execute this in procedure I'm getting error
Must declare the scalar variable "#START_TIME". 137
SP definition:
USE xxxx
/****** Object: StoredProcedure dbo.dummy Script Date: 06/09/2018 13:40:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE dbo.dummy
AS
BEGIN
/*
PRZENIESIENIE DANYCH
*/
DECLARE #START_TIME DATETIME = GETDATE()
DECLARE #TMP_NAMES TABLE (
SCHEMA_N VARCHAR(500),
TABLE_N VARCHAR(500),
CONDITION VARCHAR(MAX),
TARGETDB VARCHAR(500),
SOURCEDB VARCHAR(500),
COLUMN_LIST VARCHAR(MAX)
)
DECLARE #SCHEMA_N VARCHAR(500)
DECLARE #TABLE_N VARCHAR(500)
DECLARE #CONDITION VARCHAR(MAX)
DECLARE #COLUMN_LIST VARCHAR(MAX)
DECLARE #TARGETDB VARCHAR(500)
DECLARE #SOURCEDB VARCHAR(500)
INSERT INTO #TMP_NAMES
SELECT o.SCHEMA_N,
o.TABLE_N,
o.Condition,
o.TargetDB,
o.SourceDB,
STUFF((
SELECT ', ' + c.NAME
FROM sys.columns c
WHERE c.object_id = o.object_id
AND c.system_type_id <> 189 /* Pomijam timestamp*/
ORDER BY c.column_id
FOR XML PATH('')
), 1, 1, '')
FROM dbo.Table_A o
ORDER BY 1,
2
SELECT SCHEMA_N,
TABLE_N,
CONDITION,
TARGETDB,
SOURCEDB,
COLUMN_LIST
FROM #TMP_NAMES
DECLARE KUR CURSOR
FOR
SELECT SCHEMA_N,
TABLE_N,
CONDITION,
TARGETDB,
SOURCEDB,
COLUMN_LIST
FROM #TMP_NAMES
OPEN KUR
FETCH NEXT
FROM KUR
INTO #SCHEMA_N,
#TABLE_N,
#CONDITION,
#TARGETDB,
#SOURCEDB,
#COLUMN_LIST
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #TOP VARCHAR(100)
SET #TOP = (
SELECT CAST(Wartosc AS VARCHAR)
FROM dbo.Table_B
WHERE Id = 3
)
IF #TOP < 40000
SET #TOP = 40000
WHILE (1 = 1)
BEGIN
BEGIN TRY
BEGIN TRANSACTION T_TEST
DECLARE #CHECK BIT = 0
DECLARE #START_TIME_P DATE = GETDATE()
DECLARE #sqlCMD NVARCHAR(MAX) = 'SELECT TOP 1 #check_exists = 1 FROM ' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' WHERE ' + #CONDITION
SELECT #CHECK,
#START_TIME_P,
#sqlCMD
EXEC sp_executesql #sqlCMD,
N'#check_exists bit OUTPUT, #START_TIME DATE',
#check_exists = #CHECK OUTPUT,
#START_TIME = #START_TIME_P;
IF OBJECT_ID('tempdb..#TMP_ID') IS NOT NULL
DROP TABLE #TMP_ID
CREATE TABLE #TMP_ID (Id INT)
EXEC (
'INSERT INTO #TMP_ID
SELECT TOP ' + #TOP + ' Id
FROM ' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' WHERE ' + #CONDITION
)
DECLARE #sqlCMD_Ins NVARCHAR(MAX)
SET #sqlCMD_Ins = 'INSERT INTO ' + #TARGETDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' '
SET #sqlCMD_Ins = #sqlCMD_Ins + 'SELECT ' + #COLUMN_LIST + ' FROM ' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' WHERE Id IN ( SELECT Id FROM #TMP_ID )'
IF #sqlCMD_Ins IS NULL
RAISERROR (
'Brak polecenia insert #sqlCMD_Ins',
16,
1
)
EXEC (#sqlCMD_Ins)
DECLARE #sqlCMD_Del NVARCHAR(MAX)
SET #sqlCMD_Del = 'DELETE FROM ' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' WHERE Id IN ( SELECT Id FROM #TMP_ID )'
IF #sqlCMD_Del IS NULL
RAISERROR (
'Brak polecenia insert #sqlCMD_Ins',
16,
1
)
EXEC (#sqlCMD_Del)
DROP TABLE #TMP_ID
COMMIT TRANSACTION T_TEST
END TRY
BEGIN CATCH
IF (##TRANCOUNT > 0)
BEGIN
ROLLBACK TRANSACTION T_TEST
PRINT 'Wycofanie zmian'
PRINT ERROR_MESSAGE() + ' ' + CAST(ERROR_NUMBER() AS VARCHAR(256))
END
END CATCH
IF #CHECK = 0
BREAK
END
EXEC ('SELECT ''' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ''' AS DB ,COUNT(1) AS ILOSC FROM ' + #SOURCEDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ' UNION ALL ' + 'SELECT ''' + #TARGETDB + '.' + #SCHEMA_N + '.' + #TABLE_N + ''' AS DB ,COUNT(1) AS ILOSC FROM ' + #TARGETDB + '.' + #SCHEMA_N + '.' + #TABLE_N)
FETCH NEXT
FROM KUR
INTO #SCHEMA_N,
#TABLE_N,
#CONDITION,
#TARGETDB,
#SOURCEDB,
#COLUMN_LIST
END
CLOSE KUR;
DEALLOCATE KUR;
DECLARE #END_TIME DATETIME = GETDATE()
SELECT 'Daty przetworzenia',
#START_TIME_P AS 'START',
#END_TIME AS 'END'
SELECT 'Czas (min)',
DATEDIFF(MINUTE, #START_TIME_P, #END_TIME)
END
Guys, maybe u have similar situation and can help.
Error msg
Wycofanie zmian
Must declare the scalar variable "#START_TIME". 137
Thanks
Instead of
exec sp_executesql #sqlCMD, N'#check_exists bit OUTPUT, #START_TIME DATE', #check_exists = #CHECK OUTPUT, #START_TIME = #START_TIME;
try
declare #date_in DATE = GETDATE()
exec sp_executesql #sqlCMD, N'#check_exists bit OUTPUT, #START_TIME DATE', #check_exists = #CHECK OUTPUT, #START_TIME = #date_in;
I want to replace all e_Mail column where in #tablename with my users table (my main table).
For example:
#tablename
[name] [eMail] // columns
------------------------------------------------------
name surname blahblah#gmail.com
My users table
[name] [eMail]
----------------------------------------
name surname blahblah#hotmail.com
I want to update this row's eMail column as 'blahblah#hotmail.com' in #tablename.
What will procedure do?
1- Get first value of eMail column from #tablename
2- Split value (split char: #) and get first value (for example, if value blahblah#gmail.com, get gmail.com)
3- Search first value in users table
4- When the find value in users table, (Code must find blahblah#hotmail.com) Update eMail as blahblah#hotmail.com in #tablename
5- Get second value of eMail column from #tablename
.
.
.
So, I write a stored procedure. But this procedure is not working. Where is the problem?
Create Proc update_eMail
(#tablename nvarchar(50),
#columnname nvarchar(50))
AS
Begin
Declare #get_oldeMail nvarchar(100)
Declare #get_eMail nvarchar(100)
Declare #get_SplitValue nvarchar(100)
Declare #get_oldSplitValue nvarchar(100)
Declare #rowNumber int
Declare #users_rowNumber int
Declare #i int
Declare #j int
Declare #q_getRowNumber NVARCHAR(MAX)
Declare #q_getoldeMail NVARCHAR(MAX)
Declare #q_UpdateQuery NVARCHAR(MAX)
SET #q_getRowNumber = N'SELECT Count(ID)
FROM ' + QUOTENAME(#tablename)
EXECUTE #rowNumber = sp_executesql #q_getRowNumber
/*Set #rowNumber = (Select Count(ID) from #tablename)*/
Set #users_rowNumber = (Select Count(ID) from tblusers)
Set #i = 1
Set #j = 1
While(#i <= #rowNumber)
BEGIN
Set #q_getoldeMail = '(SELECT Lower(#columnname) FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY ID) AS rownumber
,ID
,[Name]
,[Description]
,[Status]
,[AssignedTo]
,[AssignedToMail]
,[CC]
FROM' + #tablename + '
) AS ar
WHERE rownumber = #i)'
EXECUTE #get_oldeMail = sp_executesql #q_getoldeMail
Set #get_oldeMail = REPLACE(#get_oldeMail,'ı','i')
WHILE LEN(#get_oldeMail) > 0
BEGIN
IF CHARINDEX('#',#get_oldeMail) > 0
SET #get_oldSplitValue = SUBSTRING(#get_oldeMail,0,CHARINDEX('#',#get_oldeMail))
ELSE
BEGIN
SET #get_oldSplitValue = #get_oldeMail
SET #get_oldeMail = ''
END
SET #get_oldeMail = REPLACE(#get_oldeMail,#get_oldSplitValue + '#' , '')
END
While(#j <= #users_rowNumber)
BEGIN
Set #get_eMail = (SELECT Replace(Lower(eMail),'ı','i') FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY ID) AS rownumber
,eMail
FROM tblusers) AS ar
WHERE rownumber = #j)
WHILE LEN(#get_eMail) > 0
BEGIN
IF CHARINDEX('#',#get_eMail) > 0
SET #get_SplitValue = SUBSTRING(#get_eMail,0,CHARINDEX('#',#get_eMail))
ELSE
BEGIN
SET #get_SplitValue = #get_eMail
SET #get_eMail = ''
END
SET #get_eMail = REPLACE(#get_eMail,#get_SplitValue + '#' , '')
END
if(#get_splitValue = #get_oldSplitValue)
begin
Set #q_UpdateQuery = 'Update ar Set ' + #columnname + ' = ' + #get_email + ' Where rownumber = ' +#i
EXECUTE sp_executesql #q_UpdateQuery
break
end
SET #j = #j+1
END
SET #i = #i+1
END
End
Thanks in advance.
Using this SP I keep getting an error on the UPDATE statement indicating that I have conversion problem or something. But ID is an integer in all of my tables....
Conversion failed when converting the varchar value 'UPDATE tblLangenUS SET [lang_String] = ' - asdfgsdfg', [prev_LangString] = ' ', [needsTranslation] = 'false' WHERE [ID] = '' to data type int.
#currTable varchar(100),
#ID int,
#short_Text varchar(250),
#brief_Descrip varchar(250) = Null,
#needsTranslation varchar(10) = Null,
#prev_LangString varchar(250) = Null,
#lang_String varchar(250) = Null,
#original_lang_String varchar(250) = Null,
#StringID_from_Master varchar(250),
#GUID varchar(250) = Null
/*
*/
AS
SET NOCOUNT ON;
DECLARE #userTable AS VARCHAR(200);
SET #userTable = #currTable
DECLARE #submitDate1 DATETIME;
SET #submitDate1 = GETDATE()
SET #prev_LangString = #original_lang_String
SET #needsTranslation = 'false'
DECLARE #sql varchar(max)
-- Establish update to the language tabel of user and prepare to search DB for all strings that will need to be updated.
BEGIN
SET #sql = 'UPDATE ' + #currTable + ' SET [lang_String] = ''' + #lang_String + ''', [prev_LangString] = ''' + #prev_LangString + ''', [needsTranslation] = ''' + #needsTranslation + ''' WHERE [ID] = ''' + #ID + '''; '
EXEC #sql
#sql = ''
END
BEGIN
DECLARE usedIN_DBScursor CURSOR
FOR
SELECT tblUniquetblStringsMaster_ID, Database_Name, dbKeyID_ofStringName
FROM tblDBUsage
WHERE (tblUniquetblStringsMaster_ID = #StringID_from_Master );
-- Declare the variables to store the values returned by FETCH.
DECLARE #tblUniquetblStringsMaster_ID AS INT;
DECLARE #dbKEYID as INT;
DECLARE #dbName as varchar(100);
OPEN usedIN_DBScursor;
-- Perform the first fetch and store the values in variables.
-- Note: The variables are in the same order as the columns
-- in the SELECT statement.
FETCH NEXT FROM usedIN_DBScursor
INTO #tblUniquetblStringsMaster_ID, #dbName, #dbKEYID;
-- Check ##FETCH_STATUS to see if there are any more rows to fetch.
WHILE ##FETCH_STATUS = 0
BEGIN
-- Update pending strings table with translation.
BEGIN
INSERT INTO tblPendingDBUpdates
(stringMasterID, databaseName, databaseStringID, englishText, foreignLangText, submitDate, GUID)
VALUES (#StringID_from_Master, #dbName, #dbKEYID, #short_Text, #lang_String, #submitDate1, #GUID);
END
-- SET #sql = ''
-- This is executed as long as the previous fetch succeeds.
FETCH NEXT FROM usedIN_DBScursor
INTO #tblUniquetblStringsMaster_ID, #dbName, #dbKEYID;
END
CLOSE usedIN_DBScursor;
DEALLOCATE usedIN_DBScursor;
END
RETURN
If the ID is an int, you must CAST it to an nvarchar
SET #sql = 'UPDATE ' + #currTable + ' SET [lang_String] = ''' + #lang_String + ''', [prev_LangString] = ''' + #prev_LangString + ''', [needsTranslation] = ''' + #needsTranslation + ''' WHERE [ID] = ''' + CAST(#ID as nvarchar(10)) + '''; '
Otherwise, you are trying to add a string and an integer together, which won't work.
Notice this part:
' WHERE [ID] = ''' + CAST(#ID as nvarchar(10)) + '''
I think you must also change your EXEC syntax to:
EXEC(#sql)
Is it possible via script/tool to generate a delete statement based on the tables fk relations.
i.e. I have the table: DelMe(ID) and there are 30 tables with fk references to its ID that I need to delete first, is there some tool/script that I can run that will generate the 30 delete statements based on the FK relations for me ?
(btw I know about cascade delete on the relations, I can't use it in this existing db)
I'm using Microsoft SQL Server 2008
Here is a script for cascading delete by Aasim Abdullah, works for me on MS SQL Server 2008:
IF OBJECT_ID('dbo.udfGetFullQualName') IS NOT NULL
DROP FUNCTION dbo.udfGetFullQualName;
GO
CREATE FUNCTION dbo.udfGetFullQualName
(#ObjectId INT)
RETURNS VARCHAR (300)
AS
BEGIN
DECLARE #schema_id AS BIGINT;
SELECT #schema_id = schema_id
FROM sys.tables
WHERE object_id = #ObjectId;
RETURN '[' + SCHEMA_NAME(#schema_id) + '].[' + OBJECT_NAME(#ObjectId) + ']';
END
GO
--============ Supporting Function dbo.udfGetOnJoinClause
IF OBJECT_ID('dbo.udfGetOnJoinClause') IS NOT NULL
DROP FUNCTION dbo.udfGetOnJoinClause;
GO
CREATE FUNCTION dbo.udfGetOnJoinClause
(#fkNameId INT)
RETURNS VARCHAR (1000)
AS
BEGIN
DECLARE #OnClauseTemplate AS VARCHAR (1000);
SET #OnClauseTemplate = '[<#pTable>].[<#pCol>] = [<#cTable>].[<#cCol>] AND ';
DECLARE #str AS VARCHAR (1000);
SET #str = '';
SELECT #str = #str + REPLACE(REPLACE(REPLACE(REPLACE(#OnClauseTemplate, '<#pTable>', OBJECT_NAME(rkeyid)), '<#pCol>', COL_NAME(rkeyid, rkey)), '<#cTable>', OBJECT_NAME(fkeyid)), '<#cCol>', COL_NAME(fkeyid, fkey))
FROM dbo.sysforeignkeys AS fk
WHERE fk.constid = #fkNameId; --OBJECT_ID('FK_ProductArrearsMe_ProductArrears')
RETURN LEFT(#str, LEN(#str) - LEN(' AND '));
END
GO
--=========== CASECADE DELETE STORED PROCEDURE dbo.uspCascadeDelete
IF OBJECT_ID('dbo.uspCascadeDelete') IS NOT NULL
DROP PROCEDURE dbo.uspCascadeDelete;
GO
CREATE PROCEDURE dbo.uspCascadeDelete
#ParentTableId VARCHAR (300), #WhereClause VARCHAR (2000), #ExecuteDelete CHAR (1)='N', --'N' IF YOU NEED DELETE SCRIPT
#FromClause VARCHAR (8000)='', #Level INT=0 -- TABLE NAME OR OBJECT (TABLE) ID (Production.Location) WHERE CLAUSE (Location.LocationID = 7) 'Y' IF WANT TO DELETE DIRECTLY FROM SP, IF LEVEL 0, THEN KEEP DEFAULT
AS -- writen by Daniel Crowther 16 Dec 2004 - handles composite primary keys
SET NOCOUNT ON;
/* Set up debug */
DECLARE #DebugMsg AS VARCHAR (4000),
#DebugIndent AS VARCHAR (50);
SET #DebugIndent = REPLICATE('---', ##NESTLEVEL) + '> ';
IF ISNUMERIC(#ParentTableId) = 0
BEGIN -- assume owner is dbo and calculate id
IF CHARINDEX('.', #ParentTableId) = 0
SET #ParentTableId = OBJECT_ID('[dbo].[' + #ParentTableId + ']');
ELSE
SET #ParentTableId = OBJECT_ID(#ParentTableId);
END
IF #Level = 0
BEGIN
PRINT #DebugIndent + ' **************************************************************************';
PRINT #DebugIndent + ' *** Cascade delete ALL data from ' + dbo.udfGetFullQualName(#ParentTableId);
IF #ExecuteDelete = 'Y'
PRINT #DebugIndent + ' *** #ExecuteDelete = Y *** deleting data...';
ELSE
PRINT #DebugIndent + ' *** Cut and paste output into another window and execute ***';
END
DECLARE #CRLF AS CHAR (2);
SET #CRLF = CHAR(13) + CHAR(10);
DECLARE #strSQL AS VARCHAR (4000);
IF #Level = 0
SET #strSQL = 'SET NOCOUNT ON' + #CRLF;
ELSE
SET #strSQL = '';
SET #strSQL = #strSQL + 'PRINT ''' + #DebugIndent + dbo.udfGetFullQualName(#ParentTableId) + ' Level=' + CAST (##NESTLEVEL AS VARCHAR) + '''';
IF #ExecuteDelete = 'Y'
EXECUTE (#strSQL);
ELSE
PRINT #strSQL;
DECLARE curs_children CURSOR LOCAL FORWARD_ONLY
FOR SELECT DISTINCT constid AS fkNameId, -- constraint name
fkeyid AS cTableId
FROM dbo.sysforeignkeys AS fk
WHERE fk.rkeyid <> fk.fkeyid -- WE DO NOT HANDLE self referencing tables!!!
AND fk.rkeyid = #ParentTableId;
OPEN curs_children;
DECLARE #fkNameId AS INT,
#cTableId AS INT,
#cColId AS INT,
#pTableId AS INT,
#pColId AS INT;
FETCH NEXT FROM curs_children INTO #fkNameId, #cTableId; --, #cColId, #pTableId, #pColId
DECLARE #strFromClause AS VARCHAR (1000);
DECLARE #nLevel AS INT;
IF #Level = 0
BEGIN
SET #FromClause = 'FROM ' + dbo.udfGetFullQualName(#ParentTableId);
END
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #strFromClause = #FromClause + #CRLF + ' INNER JOIN ' + dbo.udfGetFullQualName(#cTableId) + #CRLF + ' ON ' + dbo.udfGetOnJoinClause(#fkNameId);
SET #nLevel = #Level + 1;
EXECUTE dbo.uspCascadeDelete #ParentTableId = #cTableId, #WhereClause = #WhereClause, #ExecuteDelete = #ExecuteDelete, #FromClause = #strFromClause, #Level = #nLevel;
SET #strSQL = 'DELETE FROM ' + dbo.udfGetFullQualName(#cTableId) + #CRLF + #strFromClause + #CRLF + 'WHERE ' + #WhereClause + #CRLF;
SET #strSQL = #strSQL + 'PRINT ''---' + #DebugIndent + 'DELETE FROM ' + dbo.udfGetFullQualName(#cTableId) + ' Rows Deleted: '' + CAST(##ROWCOUNT AS VARCHAR)' + #CRLF + #CRLF;
IF #ExecuteDelete = 'Y'
EXECUTE (#strSQL);
ELSE
PRINT #strSQL;
FETCH NEXT FROM curs_children INTO #fkNameId, #cTableId;
--, #cColId, #pTableId, #pColId
END
IF #Level = 0
BEGIN
SET #strSQL = #CRLF + 'PRINT ''' + #DebugIndent + dbo.udfGetFullQualName(#ParentTableId) + ' Level=' + CAST (##NESTLEVEL AS VARCHAR) + ' TOP LEVEL PARENT TABLE''' + #CRLF;
SET #strSQL = #strSQL + 'DELETE FROM ' + dbo.udfGetFullQualName(#ParentTableId) + ' WHERE ' + #WhereClause + #CRLF;
SET #strSQL = #strSQL + 'PRINT ''' + #DebugIndent + 'DELETE FROM ' + dbo.udfGetFullQualName(#ParentTableId) + ' Rows Deleted: '' + CAST(##ROWCOUNT AS VARCHAR)' + #CRLF;
IF #ExecuteDelete = 'Y'
EXECUTE (#strSQL);
ELSE
PRINT #strSQL;
END
CLOSE curs_children;
DEALLOCATE curs_children;
Usage example 1
Note the use of the fully qualified column name in the example. It's subtle but you must specify the table name for the generated SQL to execute properly.
EXEC uspCascadeDelete
#ParentTableId = 'Production.Location',
#WhereClause = 'Location.LocationID = 2'
Usage example 2
EXEC uspCascadeDelete
#ParentTableId = 'dbo.brand',
#WhereClause = 'brand.brand_name <> ''Apple'''
Usage example 3
exec uspCascadeDelete
#ParentTableId = 'dbo.product_type',
#WhereClause = 'product_type.product_type_id NOT IN
(SELECT bpt.product_type_id FROM dbo.brand_product_type bpt)'
DELETE statements generated for use in SP with parameter, and as ON DELETE triggers:
(this variant supports single column FKs only)
SELECT 'DELETE '+detail.name+' WHERE '+dcolumn.name+' = #'+mcolumn.name AS stmt,
'DELETE ' + detail.name + ' FROM ' + detail.name + ' INNER JOIN deleted ON ' +
detail.name + '.' + dcolumn.name + ' = deleted.' + mcolumn.name AS trg
FROM sys.columns AS mcolumn
INNER JOIN sys.foreign_key_columns ON mcolumn.object_id =
sys.foreign_key_columns.referenced_object_id
AND mcolumn.column_id = sys.foreign_key_columns.referenced_column_id
INNER JOIN sys.tables AS master ON mcolumn.object_id = master.object_id
INNER JOIN sys.columns AS dcolumn
ON sys.foreign_key_columns.parent_object_id = dcolumn.object_id
AND sys.foreign_key_columns.parent_column_id = dcolumn.column_id
INNER JOIN sys.tables AS detail ON dcolumn.object_id = detail.object_id
WHERE (master.name = N'MyTableName')
I'm pretty sure I posted code here on Stack Overflow which does this automatically using INFORMATION_SCHEMA to generate dynamic SQL, but I can't find it. Let me see if I can regenerate it.
You might need to check this out a bit, I couldn't find my original code, so I modified some code I had which builds flattend views for star-schemas automatically.
DECLARE #COLUMN_NAME AS sysname
DECLARE #TABLE_NAME AS sysname
DECLARE #IDValue AS int
SET #COLUMN_NAME = '<Your COLUMN_NAME here>'
SET #TABLE_NAME = '<Your TABLE_NAME here>'
SET #IDValue = 123456789
DECLARE #sql AS varchar(max) ;
WITH RELATED_COLUMNS
AS (
SELECT QUOTENAME(c.TABLE_SCHEMA) + '.'
+ QUOTENAME(c.TABLE_NAME) AS [OBJECT_NAME]
,c.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS AS c WITH (NOLOCK)
INNER JOIN INFORMATION_SCHEMA.TABLES AS t WITH (NOLOCK)
ON c.TABLE_CATALOG = t.TABLE_CATALOG
AND c.TABLE_SCHEMA = t.TABLE_SCHEMA
AND c.TABLE_NAME = t.TABLE_NAME
AND t.TABLE_TYPE = 'BASE TABLE'
INNER JOIN (
SELECT rc.CONSTRAINT_CATALOG
,rc.CONSTRAINT_SCHEMA
,lkc.TABLE_NAME
,lkc.COLUMN_NAME
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
WITH (NOLOCK)
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE lkc
WITH (NOLOCK)
ON lkc.CONSTRAINT_CATALOG = rc.CONSTRAINT_CATALOG
AND lkc.CONSTRAINT_SCHEMA = rc.CONSTRAINT_SCHEMA
AND lkc.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
WITH (NOLOCK)
ON rc.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
AND rc.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
AND rc.UNIQUE_CONSTRAINT_NAME = tc.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE rkc
WITH (NOLOCK)
ON rkc.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
AND rkc.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
AND rkc.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
WHERE rkc.COLUMN_NAME = #COLUMN_NAME
AND rkc.TABLE_NAME = #TABLE_NAME
) AS j
ON j.CONSTRAINT_CATALOG = c.TABLE_CATALOG
AND j.CONSTRAINT_SCHEMA = c.TABLE_SCHEMA
AND j.TABLE_NAME = c.TABLE_NAME
AND j.COLUMN_NAME = c.COLUMN_NAME
)
SELECT #sql = COALESCE(#sql, '') + 'DELETE FROM ' + [OBJECT_NAME]
+ ' WHERE ' + [COLUMN_NAME] + ' = ' + CONVERT(varchar, #IDValue)
+ CHAR(13) + CHAR(10)
FROM RELATED_COLUMNS
PRINT #sql
Another technique is to use a code generator to create the Sql. I'm pretty sure the MyGeneration (no connection) has existing templates to do this. Using that tool and the right template you can create a sql script that deletes the relevant stuff with no pain.
Unfortunately, I think cascading is the tool you're asking for. I understand not being able to use it, but that fact that it exists as a built-in part of the db has pretty much killed the need for an alternative.
You can create all fk columns with a same name like 'row_id'
Then write the code below:
create procedure dbo.deleteRow
#row_id int
as
begin
set nocount on
begin transaction delete_row
declare #mainTableName varchar(50) = 'MyMainTableName'
begin try
declare #OBJECT_ID_mainTable int
select #OBJECT_ID_mainTable = OBJECT_ID from sys.tables where name = #mainTableName
create table #ids ( object_id int , table_name varchar (50) , referenced_object_id int , r_index int )
--1) select all tables are has fk to main table
insert into #ids select t.object id , t.name , fk.referenced object id ,
row_number () over ( order by
--how many tables are depends on me
(select COUNT ( * ) from sys . foreign_key_columns a fk where a_fk.referenced_object_id = fk.parent_object_id ) desc ) r_index
from sys.foreign_key_columns fk
join sys.tables t on t.object_id- fk.parent_object_id
where fk.referenced_object_id = #OBJECT_ID_mainTable
declare #i int = ( select max ( r_index ) from #ids )
declare #sqlBuilder nvarchar ( max )
--2) delete from fk tables in dependet order
while #i > 0
begin
--all fk column are called 'row_id'
set #sqlBuilder = concat ('delete from dbo.[' + ( select table_name from #ids where r_index = #i ) + ']' +
'where row_id = ', #row_id )
exec(#sqlBuilder)
set #i=#i-1
end
--3) delete from main table
delete from <MyMainTableName> where id = #row_id
commit transaction delete_row
end try
begin catch
rollback transaction delete_row
throw
end catch
end