AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 43262
Accepted
ErikE
ErikE
Asked: 2013-05-29 10:03:10 +0800 CST2013-05-29 10:03:10 +0800 CST 2013-05-29 10:03:10 +0800 CST

sp_executesql adiciona instruções ao script dinâmico executado?

  • 772

A Pergunta :

Tanto quanto eu posso dizer, sp_executesqladiciona instruções ao início do script SQL dinâmico enviado. Porém, um rastreamento do SQL Profiler não captura as instruções extras e nem o DBCC OUTPUTBUFFER. Então:

  1. Existe alguma maneira de ver as instruções extras adicionadas aos lotes SQL dinâmicos enviados por sp_executesql?
  2. Alguém pode confirmar definitivamente que minhas conclusões sobre as declarações extras estão corretas/incorretas?

Fundo

Eu tenho um banco de dados onde alguns objetos (views, sinônimos, SPs) são reescritos com base nos dados de uma Scripttabela. Se o banco de dados for movido para outro servidor, um procedimento armazenado percorre as linhas da Scripttabela, substitui certos valores de chave no script SQL fornecido por aqueles definidos para o novo contexto do servidor e executa o script.

Tudo estava funcionando bem até que fiz alguns ajustes para adicionar suporte para permissões de script por meio desse mesmo mecanismo. O banco de dados integra-se ao produto de um fornecedor e, em cada ambiente, o banco de dados do fornecedor pode ter um usuário diferente que deve receber permissão para uma exibição específica em meu banco de dados para fins de relatório. Portanto, tenho que consultar esse usuário (no banco de dados do fornecedor), usar esse nome para criar o usuário em meu banco de dados, se ele não existir e, finalmente, conceder SELECTpermissão. Isso exigia scripts mais demorados e fazer dynamic-sql dentro do dynamic-sql, então eu queria passar o @Debugparâmetro do meu script externo para poder ver o script extra que estava sendo gerado e confirmar sua correção antes de tentar executá-lo.

Além de alterar quais tipos de objeto podem ser incluídos no script e tornar o DROPscript opcional, a única alteração material que fiz para acomodar o @Debugparâmetro foi alterar isto:

EXEC (@CreateSQL);

para isso:

EXEC sp_executesql @CreateSQL, N'@Debug bit', @Debug;

Então me deparei com um problema: o único procedimento armazenado em minha Scripttabela não podia mais ser criado, embora o DROPanterior ainda funcionasse bem. O resultado que obtive foi este:

Msg 156, Nível 15, Estado 1, Linha 1

Sintaxe incorreta perto da palavra-chave 'PROCEDIMENTO'.

Isso foi muito confuso, mas depois de discutir com ele por algum tempo, finalmente descobri o problema: sp_executesqlvincula parâmetros ao SQL dinâmico adicionando secretamente uma DECLAREinstrução ao topo antes de executar. Como CREATE PROCEDUREdeve ser a única instrução no lote, mas agora há uma instrução extra antes da CREATE PROCEDURElinha, ela gera um erro. Ele diz Line 1- o que me enganou ainda mais - mas isso é obviamente ajustado pelo mecanismo para que as pessoas não fiquem confusas sobre os números de linha de seu próprio script ao lidar com erros.

A solução para o problema foi detectar com qual tipo de objeto estava sendo trabalhado e NÃO passar o @Debugparâmetro para que o script que não deve ter outras instruções funcione bem. Uma mudança rápida fez o trabalho:

IF @ScriptType IN ('Procedure', 'View', 'Function') BEGIN
   EXEC sp_executesql @CreateSQL;
END
ELSE BEGIN
   EXEC sp_executesql @CreateSQL, N'@Debug bit', @Debug;
END;

Eu também poderia ter aninhado meu SQL dinâmico um nível mais profundo, para criar o procedimento dentro do SQL dinâmico (novamente, dentro do script na tabela), mas essa foi uma solução menos ideal no meu caso.

Suspeito que o uso OUTPUTde variáveis ​​com sp_executesqltambém adicionaria uma ou mais instruções ao final do script para permitir que o mecanismo as capture, provavelmente em uma SELECTinstrução que é silenciosamente engolida.

sql-server dynamic-sql
  • 2 2 respostas
  • 3256 Views

2 respostas

  • Voted
  1. Richard Schweiger
    2013-05-29T10:20:35+08:002013-05-29T10:20:35+08:00

    Antes do sp_executesql, você deve ver uma instrução sp_prepare no Profiler que forneceria mais informações: http://msdn.microsoft.com/en-us/library/ff848808(v=sql.110).aspx

    Às vezes, isso pode ser difícil de encontrar, mas ficou um pouco mais fácil com eventos estendidos em 2008R2 - especificamente rastreamento de causalidade.

    http://msdn.microsoft.com/en-us/library/bb630284.aspx

    • 4
  2. Best Answer
    ErikE
    2013-05-30T18:24:51+08:002013-05-30T18:24:51+08:00

    Descobri que o servidor não coloca o conteúdo do script injetado no lote, mas no plano de execução em cache. Então, você só pode ver isso acontecendo no profiler se o SQL dinâmico executado não estiver no cache. Isso me confundiu originalmente porque só comecei a rastrear depois de executar meu teste uma vez, então a instrução já estava no cache. Finalmente encontrei esse evento quando troquei os servidores de banco de dados e tive o rastreamento em execução na primeira execução.

    Aqui está o lote que executei:

    DECLARE @SQL nvarchar(4000), @Debug bit;
    SET @SQL = 'WAITFOR DELAY ''00:00:20'';';
    EXEC sp_executesql @SQL, N'@Debug bit OUTPUT', @Debug OUTPUT;
    

    E aqui está o que eu encontrei na SQL Profiler 10.0.1600.22corrida contra Microsoft SQL Server 2008 R2 (SP2) - 10.50.4263.0 (X64):

    Event: SP:CacheInsert
    Submitted SQL text: WAITFOR DELAY '00:00:20';
    Text placed in cache: (@Debug bit OUTPUT)WAITFOR DELAY '00:00:20';
    

    Então eu estava certo que há texto sendo injetado, mas errado em alguns pontos:

    1. Não é uma DECLAREdeclaração normal. É outra coisa. O que é isso... fique ligado.

    2. Quando há variáveis ​​OUTPUT, ele é tratado mais como um procedimento armazenado com uma OUTPUTvariável. Não há nenhum conteúdo oculto SELECTou outro adicionado ao final, como os drivers do provedor de banco de dados geralmente fazem aos lotes enviados para coletar valores de retorno ou contagens de linhas.

    3. Não há nenhum ajuste de número de linha acontecendo. O script extra é adicionado ao início sem quebras de linha.

    Se você tentar enviar o texto completo em cache diretamente, receberá um erro:

    (@Debug bit OUTPUT)WAITFOR DELAY '00:00:20';
    

    Msg 1050, Nível 15, Estado 1, Linha 1

    Esta sintaxe só é permitida para consultas parametrizadas.

    Portanto, parece que o termo correto é uma "consulta parametrizada". Embora o termo normalmente se refira à codificação front-end, aparentemente existe um tipo interno de SQL Server que é usado em SQL armazenado em cache em planos de execução.

    • 2

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Conceder acesso a todas as tabelas para um usuário

    • 5 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve