【问题标题】:How to generate an update query of a dynamic query (automatically)?如何(自动)生成动态查询的更新查询?
【发布时间】:2013-06-05 19:57:44
【问题描述】:

我将一些查询存储在表列中,以便稍后通过一些参数执行它们。 但是由于特殊字符,将查询格式化为更新语句真的很烦人。

例如:

SELECT * FROM MOUNTAINS WHERE MON_NAME='PALMA' AND MON_DESC LIKE '%TRANVULCANIA%'

那么我只需要用于 udpate 查询的字符串:

UPDATE QUERIES 
SET QUE_SEL='SELECT * FROM MOUNTAINS WHERE MON_NAME='''+'PALMA'+''' AND MON_DESC LIKE '''+'%TRANVULCANIA%'+''' '
WHERE QUE_ID=1

如您所见,第一个 ' 必须替换为 '''+' 但隔壁 ' 必须替换为 '+'''

这是我正在处理的查询:

DECLARE @QUERY VARCHAR(MAX)

SELECT @QUERY='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'+''' '

SELECT 
      t.r.value('.', 'varchar(255)') AS token
    , ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS id
FROM (
    SELECT myxml = CAST('<t>' + REPLACE(@QUERY, '''', '</t><t>''</t><t>') + '</t>' AS XML)
        ) p
        CROSS APPLY myxml.nodes('/t') t(r)

这是结果:

token                                              id
-------------------------------------------------- --------------------
SELECT * FROM QUERIES WHERE QUE_NOMBRE=            1
'                                                  2
PRUEBA 1                                           3
'                                                  4
                                                   5

现在我想要一列告诉我何时打开和何时关闭,然后我可以设置最终替换。

【问题讨论】:

  • 你是否考虑过命名参数,如SELECT * FROM Table WHERE Column = @Value
  • 只是一个例子..我当然使用@values,但我在查询中使用了一些xml,所以我需要使用'

标签: sql sql-server sql-server-2008 tsql formatting


【解决方案1】:

调整@rivarolle 给出的解决方案

DECLARE @QUERY VARCHAR(MAX)
DECLARE @FORMATTED varchar(max)

SELECT @QUERY='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'+''''

;WITH TOKENS AS(
SELECT 
      t.r.value('.', 'varchar(MAX)') AS token
      , ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS Id 
FROM (
        SELECT myxml = CAST('<t>' + REPLACE(@QUERY, '''', '</t><t>''</t><t>') + '</t>' AS XML)
            ) p
            CROSS APPLY myxml.nodes('/t') t(r)
    ) 
    ,

Tokens2 as (
        SELECT 
        TOKENS.token as token
        ,quotes.row%2 as tipoapostrofe
from Tokens 
left join (select row_number() over( order by Id asc) as row, a.* FROM (SELECT * from Tokens) a where Token = '''') quotes 
    on quotes.Id = Tokens.Id
)

SELECT @FORMATTED = STUFF((
    SELECT ' ' + REPLACE(token,'''',CASE tipoapostrofe WHEN 1 THEN '''''''+''' WHEN 0 THEN '''+''''''' ELSE '' END) AS [text()]
    FROM Tokens2
FOR XML PATH('')
    ), 1, 1, '')
print @FORMATTED

这可行,只需要一个用于清除 XML 特殊字符的函数和另一个用于放回的函数,并且打印动态查询以准备更新。

【讨论】:

    【解决方案2】:

    我认为没有必要将撇号替换为 '''+' 来打开和 '+''' 来关闭,我做了一些探测,您可以执行一个查询,将开始和关闭撇号替换为相同的撇号。 . 例如,'''+' 表示打开,'''+' 表示关闭。

    所以查询将是:

    DECLARE @QUERY VARCHAR(MAX)
    DECLARE @FORMATTED varchar(max)
    
    SELECT @QUERY='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'+''''
    
    SELECT @FORMATTED= STUFF((
        SELECT ' ' +
             (SELECT 
                CASE 
                    WHEN t.r.value('.', 'varchar(250)')='''' THEN REPLACE(t.r.value('.', 'varchar(250)'), '''','''''''+''')
                    ELSE t.r.value('.', 'varchar(250)')
                END
             ) AS [text()] 
    --      , ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS id
        FROM (
            SELECT myxml = CAST('<t>' + REPLACE(@QUERY, '''', '</t><t>''</t><t>') + '</t>' AS XML)
                ) p
                CROSS APPLY myxml.nodes('/t') t(r)
    FOR XML PATH('')
    ), 1, 1, '')
    
    SET @FORMATTED=REPLACE(@FORMATTED,'&#x20;','')
    PRINT @FORMATTED
    

    然后我得到:

    SELECT * FROM QUERIES WHERE QUE_NOMBRE= '''+' PRUEBA 1 '''+'
    

    然后我复制到一个变量中并执行

    DECLARE @VAR VARCHAR(500)
    SET @VAR='SELECT * FROM QUERIES WHERE QUE_NOMBRE='''+'PRUEBA 1'''+' '
    EXEC(@VAR)
    

    它适用于非常简单的查询,但对于较长和复杂的查询它不起作用..

    【讨论】:

    • @devart 此答案不起作用,有时仅在运行时失败(消息 9436,级别 16,状态 1,第 9 行 XML 解析:第 41 行,字符 57,结束标记与开始标记不匹配)或当我想执行结果时,因为打开的撇号必须由关闭的撇号关闭;我坚持认为它可以只使用左撇号,但它不会那样工作。
    • 请提供有关此问题的任何查询或示例。
    【解决方案3】:

    假设你的token表是Tokens(Token, Id, Position):

    update Tokens
         set position = quotes.row%2
    from Tokens 
    left join (select row_number() over( order by Id asc) as row, a.* FROM (SELECT * from Tokens) a where Token = '''') quotes 
        on quotes.Id = Tokens.Id
    

    位置列的起始报价为 1,结束报价为 0。其余为 NULL。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-12
      • 1970-01-01
      • 1970-01-01
      • 2018-08-02
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 2018-12-15
      相关资源
      最近更新 更多