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 / 30754
Accepted
Dan
Dan
Asked: 2012-12-20 08:35:55 +0800 CST2012-12-20 08:35:55 +0800 CST 2012-12-20 08:35:55 +0800 CST

Como faço para verificar um parâmetro com valor de tabela nulo ou vazio?

  • 772

Eu tenho um procedimento armazenado (SS2k8) com alguns parâmetros com valor de tabela que às vezes serão nulos ou vazios. Eu vi este post do StackOverflow que diz que TVPs nulos/vazios devem simplesmente ser omitidos da lista de parâmetros de chamada. Meu problema é que não consigo descobrir como verificar vazio ou nulo dentro do procedimento armazenado, pois "IF (@tvp IS NULL)" falha na criação do procedimento com a mensagem 'Deve declarar a variável escalar "@tvp"'. Eu tenho que fazer um SELECT COUNT(*) no TVP e checar por zero?

Trecho do código:

CREATE PROCEDURE [foo] (@tvp [TvpType] READONLY) AS

IF (@tvp IS NOT NULL) -- doesn't work
BEGIN
  -- lots of expensive processing
END
ELSE
BEGIN
  -- a little bit of cheap processing
END
...
sql-server sql-server-2008
  • 3 3 respostas
  • 33356 Views

3 respostas

  • Voted
  1. Best Answer
    Aaron Bertrand
    2012-12-20T08:51:23+08:002012-12-20T08:51:23+08:00

    Uma mesa não pode ser NULL, nem um TVP. Como verificar se uma tabela está vazia? Você certamente não diz IF Sales.SalesOrderHeader IS NULL. :-)

    IF EXISTS (SELECT 1 FROM @tvp)
    BEGIN
      -- lots of expensive processing
    END
    ELSE
    BEGIN
      -- a little bit of cheap processing
    END
    ...
    
    • 19
  2. billinkc
    2012-12-20T08:52:09+08:002012-12-20T08:52:09+08:00

    O parâmetro com valor de tabela não será nulo. Trate-o mais como uma mesa e @aaraon Bertrand me venceu. Então, sim, verifique se há linhas.

    • 3
  3. Dai
    2022-03-02T17:19:45+08:002022-03-02T17:19:45+08:00

    Solução alternativa 1: bitparâmetros:

    Como uma solução alternativa, garanto que cada parâmetro opcional com valor de tabela tem um parâmetro "ignorar" associado com um valor padrão de, 0portanto, é opt-in, por exemplo

    CREATE PROCEDURE dbo.UpsertNewData
        @newData1       dbo.MyDataTableType1 READONLY,
        @newData2       dbo.MyDataTableType2 READONLY,
        @ignoreNewData1 bit = 0,
        @ignoreNewData2 bit = 0
    AS
    
    SET XACT_ABORT ON; /* <-- Very important! */
    
    IF @ignoreNewData1 <> 0
    BEGIN
    
        MERGE INTO dbo.Table1 AS tgt
        FROM @newData1 AS src
        -- etc
    
    END;
    
    IF @ignoreNewData2 <> 0
    BEGIN
    
        MERGE INTO dbo.Table2 AS tgt
        FROM @newData2 AS src
        -- etc
    
    END;
    
    RETURN 0;
    

    ... claro, se o seu procedimento for destrutivo (por exemplo, você usa MERGEcom WHEN NOT MATCHED BY SOURCE THEN DELETE), então você pode torná-lo seguro por padrão, tornando os @ignore...parâmetros padrão em 1vez de 0.

    Solução alternativa 2: outro parâmetro com valor de tabela que lista parâmetros ignoráveis:

    Outra opção, especialmente se você tiver muitos parâmetros com valor de tabela, é usar outro TVP que armazene uma lista de nomes de parâmetros válidos ou ignoráveis, por exemplo

    CREATE TABLE dbo.ParameterNames TABLE (
        "Name" sysname NOT NULL PRIMARY KEY
    );
    
    GO
    
    CREATE PROCEDURE dbo.UpsertNewData
        @newData1       dbo.MyDataTableType1 READONLY,
        @newData2       dbo.MyDataTableType2 READONLY,
        @useParams      dbo.ParameterNames   READONLY
    AS
    
    SET XACT_ABORT ON; /* <-- Very important! */
    
    IF EXISTS( SELECT 1 FROM @useParams WHERE "Name" = '@newData1' )
    BEGIN
    
        MERGE INTO dbo.Table1 AS tgt
        FROM @newData1 AS src
        -- etc
    
    END;
    
    IF EXISTS( SELECT 1 FROM @useParams WHERE "Name" = '@newData2' )
    BEGIN
    
        MERGE INTO dbo.Table2 AS tgt
        FROM @newData2 AS src
        -- etc
    
    END;
    
    RETURN 0;
    

    Solução alternativa 3: use #temporarytabelas

    • Se adicionar novos parâmetros não for uma opção, você pode usar uma tabela temporária local de maneira semelhante à solução alternativa 2 descrita acima (para listar os parâmetros que devem ser ignorados ou não devem ser ignorados).
    • O chamador do procedimento precisará criar (e descartar) a tabela temporária.
      • O chamador pode ser outro procedimento ou um lote de instruções brutas .
      • Certifique-se de envolver a EXECUTEinstrução em um TRY/CATCHbloco para garantir que o #temporaryTableserá descartado.
        • Infelizmente o T-SQL não tem um FINALLYbloco, então o código resultante requer a duplicação da DROP TABLEinstrução .
    • Eu não sou um especialista em SQL Server, então não tenho certeza de como isso se comportaria com procedimentos reentrantes (mas você provavelmente não deveria ter procedimentos reentrantes de qualquer maneira)
    
    DECLARE @data1 dbo.MyDataTableType1;
    DECLARE @data2 dbo.MyDataTableType1;
    DECLARE @data3 dbo.MyDataTableType1;
    
    CREATE TABLE #ignoreParameterNames TABLE (
        "Name" sysname NOT NULL PRIMARY KEY
    );
    
    INSERT INTO #ignoreParameterNames ( "Name" )
    VALUES
    ( '@newData2' ),
    ( '@newData3' );
    
    BEGIN TRY
    
        DECLARE @rc int
        EXECUTE @rc = dbo.UpsertNewData @newData1 = @data1, DEFAULT, DEFAULT;
        IF OBJECT_ID('tempdb..#ignoreParameterNames') IS NOT NULL DROP TABLE #ignoreParameterNames;
    END TRY
    BEGIN CATCH
        IF OBJECT_ID('tempdb..#ignoreParameterNames') IS NOT NULL DROP TABLE #ignoreParameterNames;
        THROW;
    END CATCH;
    
    • 0

relate perguntas

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

  • Quanto "Padding" coloco em meus índices?

  • Existe um processo do tipo "práticas recomendadas" para os desenvolvedores seguirem para alterações no banco de dados?

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

  • Downgrade do SQL Server 2008 para 2005

Sidebar

Stats

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

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 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

    Como selecionar a primeira linha de cada grupo?

    • 6 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
    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
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +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