首页 > 解决方案 > T-SQL 如何从带有命令列表的参数中获取最后一个 T-Sql 命令

问题描述

我的应用程序在一个参数中向 sql 发送了一些命令,我​​需要仅包含最后一个命令的文本子串并执行它。我知道,最后一个命令是从“select”开始的,而不是从“declare”开始,最后一个语句可能很复杂,例如内部选择,或者只是“select * from ....”

在我的应用程序(系统报告)中,管理员用户准备了语句列表(类似于在 t-sql 中创建过程),最后一条语句始终是带有结果的表。我的任务是通过 SQL 代理使用这些语句作为夜间 XML 格式的预准备结果。我需要添加到最后一条语句“select( xml 路径的最后一条语句 ('Table'))”。如何找到最后一条语句。

例如


set @commands = 
'select * from table1 

 select A, b=(select top 1 id from table3 where id >10) from table2

 select Number, count(*) from table3 group by Number

 select *, b=(select top 1 id from table3 where id >10) from table2), x.Total 
  from table4 y
  inner join (select Id, date from table5) x on  x.Id = y.Id
'

declare @lastCommand = ....

execute (@lastCommand) ```

标签: sql-servertsql

解决方案


代码找到最后一个 SELECT 语句。我假设 SELECT 语句中的任何重复单词“SELECT”总是在圆括号之间,例如

select *, b=(select top 1 id from table3 where id >10), x.Total from table4 y inner join (select Id, date from table5) x on x.Id = y.Id'。

代码创建命令副本并通过用空格替换字母“S”来破坏 SELECT 语句内部的任何“选择”字。然后查找最后一条语句位置的程序是在命令副本中搜索最后一个“选择”字。

declare @commands varchar(max) 
set @commands = 
'select * from table1 

 select A, b=(select top 1 id from table3 where id >10) from table2

 select Number, count(*) from table3 group by Number

 select *, b=(select top 1 id from table3 where id >10), x.Total 
  from table4 y
  inner join (select Id, date from table5) x on  x.Id = y.Id
  
 '

declare @CopyOfCommands varchar(max)
set @CopyOfCommands = @commands
declare @lenCommandsText int  
declare @i int = 0 
declare @brockets int = 0
set @lenCommandsText = LEN(@CopyOfCommands)

while (@i < @lenCommandsText) 
--Replacing any 'select' word to ' elect'  between brockets
begin
    if ((SUBSTRING(@CopyOfCommands,@i,1)) = '(')    
        set @brockets = @brockets + 1
    else if ((SUBSTRING(@CopyOfCommands,@i,1)) = ')')   
        set @brockets = @brockets - 1
    else if ((UPPER(SUBSTRING(@CopyOfCommands,@i,1))) = 'S' and @brockets > 0)
        set @CopyOfCommands = SUBSTRING(@CopyOfCommands,0,@i) + ' ' + SUBSTRING(@CopyOfCommands,@i+1,@lenCommandsText - @i)
    set @i = @i + 1
end
--  Finding a position of the word 'SELECT' in the reverse text of commands (Word 'SELECT' => 'TCELES'). Converting result to reverse position in original commands list
declare @lastCommand varchar(max)
set @lastCommand = (select SUBSTRING(@commands,@lenCommandsText - CHARINDEX('TCELES',Upper(REVERSE(@CopyOfCommands)))-4,CHARINDEX('TCELES',Upper(REVERSE(@CopyOfCommands)))+5))

select @lastCommand
--execute (@lastCommand)

推荐阅读