Guest User

Untitled

a guest
Nov 22nd, 2017
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.71 KB | None | 0 0
  1. create proc dbo.sp_MSforeach_worker
  2. @command1 nvarchar(2000), @replacechar nchar(1) = N'?', @command2 nvarchar(2000) = null, @command3 nvarchar(2000) = null, @worker_type int =1
  3. as
  4.  
  5. create table #qtemp ( -- Temp command storage --
  6. qnum int NOT NULL,
  7. qchar nvarchar(2000) COLLATE database_default NULL
  8. )
  9.  
  10. set nocount on
  11. declare @name nvarchar(517), @namelen int, @q1 nvarchar(2000), @q2 nvarchar(2000)
  12. declare @q3 nvarchar(2000), @q4 nvarchar(2000), @q5 nvarchar(2000)
  13. declare @q6 nvarchar(2000), @q7 nvarchar(2000), @q8 nvarchar(2000), @q9 nvarchar(2000), @q10 nvarchar(2000)
  14. declare @cmd nvarchar(2000), @replacecharindex int, @useq tinyint, @usecmd tinyint, @nextcmd nvarchar(2000)
  15. declare @namesave nvarchar(517), @nametmp nvarchar(517), @nametmp2 nvarchar(258)
  16.  
  17. declare @local_cursor cursor
  18. if @worker_type=1
  19. set @local_cursor = hCForEachDatabase
  20. else
  21. set @local_cursor = hCForEachTable
  22.  
  23. open @local_cursor
  24. fetch @local_cursor into @name
  25.  
  26. -- Loop for each database --
  27. while (@@fetch_status >= 0) begin
  28. -- Initialize. --
  29.  
  30. -- save the original dbname --
  31. select @namesave = @name
  32. select @useq = 1, @usecmd = 1, @cmd = @command1, @namelen = datalength(@name)
  33. while (@cmd is not null) begin -- Generate @q* for exec() --
  34. ----
  35. -- * Parse each @commandX into a single executable batch.
  36. -- * Because the expanded form of a @commandX may be > OSQL_MAXCOLLEN_SET, we'll need to allow overflow.
  37. -- * We also may append @commandX's (signified by '++' as first letters of next @command).
  38. -- --
  39. select @replacecharindex = charindex(@replacechar, @cmd)
  40. while (@replacecharindex <> 0) begin
  41.  
  42. -- 7.0, if name contains ' character, and the name has been single quoted in command, double all of them in dbname --
  43. -- if the name has not been single quoted in command, do not doulbe them --
  44. -- if name contains ] character, and the name has been [] quoted in command, double all of ] in dbname --
  45. select @name = @namesave
  46. select @namelen = datalength(@name)
  47. declare @tempindex int
  48. if (substring(@cmd, @replacecharindex - 1, 1) = N'''') begin
  49. -- if ? is inside of '', we need to double all the ' in name --
  50. select @name = REPLACE(@name, N'''', N'''''')
  51. end else if (substring(@cmd, @replacecharindex - 1, 1) = N'[') begin
  52. -- if ? is inside of [], we need to double all the ] in name --
  53. select @name = REPLACE(@name, N']', N']]')
  54. end else if ((@name LIKE N'%].%]') and (substring(@name, 1, 1) = N'[')) begin
  55. -- ? is NOT inside of [] nor '', and the name is in [owner].[name] format, handle it --
  56. -- !!! work around, when using LIKE to find string pattern, can't use '[', since LIKE operator is treating '[' as a wide char --
  57. select @tempindex = charindex(N'].[', @name)
  58. select @nametmp = substring(@name, 2, @tempindex-2 )
  59. select @nametmp2 = substring(@name, @tempindex+3, len(@name)-@tempindex-3 )
  60. select @nametmp = REPLACE(@nametmp, N']', N']]')
  61. select @nametmp2 = REPLACE(@nametmp2, N']', N']]')
  62. select @name = N'[' + @nametmp + N'].[' + @nametmp2 + ']'
  63. end else if ((@name LIKE N'%]') and (substring(@name, 1, 1) = N'[')) begin
  64. -- ? is NOT inside of [] nor '', and the name is in [name] format, handle it --
  65. -- j.i.c., since we should not fall into this case --
  66. -- !!! work around, when using LIKE to find string pattern, can't use '[', since LIKE operator is treating '[' as a wide char --
  67. select @nametmp = substring(@name, 2, len(@name)-2 )
  68. select @nametmp = REPLACE(@nametmp, N']', N']]')
  69. select @name = N'[' + @nametmp + N']'
  70. end
  71. -- Get the new length --
  72. select @namelen = datalength(@name)
  73.  
  74. -- start normal process --
  75. if (datalength(@cmd) + @namelen - 1 > 2000) begin
  76. -- Overflow; put preceding stuff into the temp table --
  77. if (@useq > 9) begin
  78. close @local_cursor
  79. if @worker_type=1
  80. deallocate hCForEachDatabase
  81. else
  82. deallocate hCForEachTable
  83.  
  84. RAISERROR(55555, 16, 1); -- N'sp_MSforeach_worker assert failed: command too long'
  85. return 1
  86. end
  87. if (@replacecharindex < @namelen) begin
  88. -- If this happened close to beginning, make sure expansion has enough room. --
  89. -- In this case no trailing space can occur as the row ends with @name. --
  90. select @nextcmd = substring(@cmd, 1, @replacecharindex)
  91. select @cmd = substring(@cmd, @replacecharindex + 1, 2000)
  92. select @nextcmd = stuff(@nextcmd, @replacecharindex, 1, @name)
  93. select @replacecharindex = charindex(@replacechar, @cmd)
  94. insert #qtemp values (@useq, @nextcmd)
  95. select @useq = @useq + 1
  96. continue
  97. end
  98. -- Move the string down and stuff() in-place. --
  99. -- Because varchar columns trim trailing spaces, we may need to prepend one to the following string. --
  100. -- In this case, the char to be replaced is moved over by one. --
  101. insert #qtemp values (@useq, substring(@cmd, 1, @replacecharindex - 1))
  102. if (substring(@cmd, @replacecharindex - 1, 1) = N' ') begin
  103. select @cmd = N' ' + substring(@cmd, @replacecharindex, 2000)
  104. select @replacecharindex = 2
  105. end else begin
  106. select @cmd = substring(@cmd, @replacecharindex, 2000)
  107. select @replacecharindex = 1
  108. end
  109. select @useq = @useq + 1
  110. end
  111. select @cmd = stuff(@cmd, @replacecharindex, 1, @name)
  112. select @replacecharindex = charindex(@replacechar, @cmd)
  113. end
  114.  
  115. -- Done replacing for current @cmd. Get the next one and see if it's to be appended. --
  116. select @usecmd = @usecmd + 1
  117. select @nextcmd = case (@usecmd) when 2 then @command2 when 3 then @command3 else null end
  118. if (@nextcmd is not null and substring(@nextcmd, 1, 2) = N'++') begin
  119. insert #qtemp values (@useq, @cmd)
  120. select @cmd = substring(@nextcmd, 3, 2000), @useq = @useq + 1
  121. continue
  122. end
  123.  
  124. -- Now exec() the generated @q*, and see if we had more commands to exec(). Continue even if errors. --
  125. -- Null them first as the no-result-set case won't. --
  126. select @q1 = null, @q2 = null, @q3 = null, @q4 = null, @q5 = null, @q6 = null, @q7 = null, @q8 = null, @q9 = null, @q10 = null
  127. select @q1 = qchar from #qtemp where qnum = 1
  128. select @q2 = qchar from #qtemp where qnum = 2
  129. select @q3 = qchar from #qtemp where qnum = 3
  130. select @q4 = qchar from #qtemp where qnum = 4
  131. select @q5 = qchar from #qtemp where qnum = 5
  132. select @q6 = qchar from #qtemp where qnum = 6
  133. select @q7 = qchar from #qtemp where qnum = 7
  134. select @q8 = qchar from #qtemp where qnum = 8
  135. select @q9 = qchar from #qtemp where qnum = 9
  136. select @q10 = qchar from #qtemp where qnum = 10
  137. truncate table #qtemp
  138. exec (@q1 + @q2 + @q3 + @q4 + @q5 + @q6 + @q7 + @q8 + @q9 + @q10 + @cmd)
  139. select @cmd = @nextcmd, @useq = 1
  140. end -- while @cmd is not null, generating @q* for exec() --
  141.  
  142. -- All commands done for this name. Go to next one. --
  143. fetch @local_cursor into @name
  144. end -- while FETCH_SUCCESS --
  145. close @local_cursor
  146. if @worker_type=1
  147. deallocate hCForEachDatabase
  148. else
  149. deallocate hCForEachTable
  150.  
  151. return 0
Add Comment
Please, Sign In to add comment