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 / user-2561

WileCau's questions

Martin Hope
WileCau
Asked: 2015-04-13 18:29:38 +0800 CST

Como obter o valor de retorno de um procedimento armazenado executado com sp_executesql

  • 1

Preciso chamar um procedimento armazenado em outro banco de dados e verificar o valor de retorno. O nome do outro banco de dados pode variar, então estou tentando usar sp_executesql, mas não consegui descobrir como obter o valor de retorno do procedimento.

Esta é uma versão simplificada do que eu tenho:

DECLARE @errorLogId INT
DECLARE @otherDbName NVARCHAR(MAX) = 'Foo' -- Get the database name from somewhere
DECLARE @sql NVARCHAR(MAX)

SET @sql = @otherDbName + '.dbo.SomeProc'

-- I want @errorLogId to be the return value from SomeProc, this didn't work.    
EXECUTE @errorLogId = sp_executesql @sql

IF @errorLogId <> 0
   RAISERROR('SomeProc failed, ErrorLogId = %d.', 16, 1, @errorLogId) WITH SETERROR

Se ocorrer um erro em SomeProc, ele for detectado e uma entrada for gravada em uma tabela de erros (no outro banco de dados), SomeProc retornará o ID da tabela de erros (identidade) do registro que foi gravado. Caso contrário, SomeProc retornará 0.

Eu sei que SomeProc está falhando porque um erro é gravado no log de erros no outro banco de dados, mas no banco de dados local @errorLogId é 0, que é tratado como sucesso. Eu pensei que o valor de retorno seria 'passado' sp_executesql, mas acho que o valor de retorno é realmente de sp_executesql não SomeProc (ou seja, sp_executesql pode ser bem-sucedido independentemente de SomeProc ter sucesso ou falhado).

Existe uma maneira de acessar o valor de retorno de @otherDbName.dbo.SomeProc no banco de dados local?

Obrigado

sql-server sql-server-2008-r2
  • 3 respostas
  • 28676 Views
Martin Hope
WileCau
Asked: 2014-02-25 16:37:07 +0800 CST

Existem motivos para não usar SCHEMABINDING em objetos de banco de dados?

  • 3

Não usar a ligação de esquema parece desativar os avisos do compilador - você não descobre que quebrou algo até o tempo de execução.

O benefício é que os objetos vinculados ao esquema protegem o banco de dados de alterações acidentais ou deliberadas que podem interromper as dependências posteriormente.

O custo da proteção é que a manutenção é mais complicada porque os objetos vinculados ao esquema às vezes exigem a alteração de vários objetos em uma ordem específica para obter o que, de outra forma, seria uma simples alteração localizada. Esse custo é relativo, pois sem a vinculação do esquema, uma alteração pode interromper silenciosamente algo que exija mais manutenção posteriormente.

Acho que o benefício supera o custo, especialmente para bancos de dados estabelecidos que não estão mudando muito (menos alterações, menos manutenção) ou onde você não conhece as dependências (menos familiares, portanto, mais riscos).

Existem situações em que a associação de esquema não deve ser usada?

sql-server sql-server-2008-r2
  • 1 respostas
  • 1363 Views
Martin Hope
WileCau
Asked: 2014-01-20 20:34:48 +0800 CST

Um índice filtrado melhora a pesquisa na condição oposta?

  • 0

Ter um índice filtrado em uma coluna melhora as consultas com uma cláusula WHERE que é o oposto da condição do filtro?

Como o índice filtrado especifica o que não retornar, ele reduz o número de registros a serem pesquisados?

Exemplo:

CREATE TABLE MyTable
(
  ColumnA INT PRIMARY KEY CLUSTERED,
  ColumnB INT NULL
)

CREATE NONCLUSTERED INDEX IX_MyTable_Filtered_ColumnB
  ON MyTable (ColumnB)
  WHERE ColumnB IS NOT NULL

O índice deve melhorar esta consulta:

SELECT ColumnA
FROM MyTable
WHERE ColumnB IS NOT NULL

Isso fará alguma diferença para este?

SELECT ColumnA
FROM MyTable
WHERE ColumnB IS NULL
sql-server-2008
  • 1 respostas
  • 52 Views
Martin Hope
WileCau
Asked: 2013-07-31 03:20:34 +0800 CST

Como selecionar em uma tabela sem incluir valores de coluna repetidos?

  • 5

Em uma pergunta anterior Como mesclar conjuntos de dados sem incluir linhas redundantes? Perguntei sobre a filtragem de dados históricos redundantes durante a importação, mas @DavidSpillett respondeu corretamente que não poderia fazer o que estava tentando fazer.

Em vez de filtrar a tabela durante a importação, agora quero criar uma exibição na tabela que retorne apenas os registros em que o preço foi alterado.

Aqui está o cenário original reformulado para atender a esta pergunta:

Temos uma tabela de preços históricos dos itens. A tabela contém linhas onde o mesmo preço é registrado para várias datas. Quero criar uma visão sobre esses dados que mostre apenas as alterações de preço ao longo do tempo, portanto, se um preço mudar de A para BI, quero vê-lo, mas se "mudar" de B para B, não quero vê-lo .

Exemplo: se o preço ontem foi $ 1, e o preço hoje é $ 1, e não houve outras mudanças de preço, então o preço hoje pode ser inferido do preço ontem, então eu só preciso do registro de ontem.

Exemplo ( http://sqlfiddle.com/#!3/c95ff/1 ):

Table data:

Effective            Product  Kind  Price
2013-04-23T00:23:00  1234     1     1.00
2013-04-24T00:24:00  1234     1     1.00 -- redundant, implied by record 1
2013-04-25T00:25:00  1234     1     1.50
2013-04-26T00:26:00  1234     1     2.00
2013-04-27T00:27:00  1234     1     2.00 -- redundant, implied by record 4
2013-04-28T00:28:00  1234     1     1.00 -- not redundant, price changed back to 1.00

Expected view data:

Effective            Product  Kind  Price
2013-04-23T00:23:00  1234     1     1.00
2013-04-25T00:25:00  1234     1     1.50
2013-04-26T00:26:00  1234     1     2.00
2013-04-28T00:28:00  1234     1     1.00

Minha tentativa inicial usou ROW_NUMBER:

SELECT
    Effective,
    Product,
    Kind,
    Price
FROM
(
    SELECT
        History.*,
        ROW_NUMBER() OVER
        (
            PARTITION BY
                Product,
                Kind,
                Price
            ORDER BY
                Effective ASC
        ) AS RowNumber
    FROM History
) H
WHERE RowNumber = 1
ORDER BY Effective

Que retornou:

Effective               Product  Kind  Price
2013-04-23T00:23:00     1234     1     1.00
                                             -- not 2013-04-24, good
2013-04-25T00:25:00     1234     1     1.50
2013-04-26T00:26:00     1234     1     2.00
                                             -- not 2013-04-27, good
                                             -- not 2013-04-28, bad

Tentei pesquisar por uma pergunta/resposta semelhante, mas é difícil descobrir como formular a pesquisa, um exemplo vale muitas palavras.

Qualquer sugestão é apreciada. Obrigado

sql-server-2008
  • 5 respostas
  • 9784 Views
Martin Hope
WileCau
Asked: 2013-06-04 18:49:47 +0800 CST

Como mesclar conjuntos de dados sem incluir linhas redundantes?

  • 2

Acho que isso deve ser uma coisa bastante comum de se fazer, mas não consegui encontrar um exemplo. Envolve a mesclagem de dados que envolvem datas/horas (ou mais geralmente quaisquer valores sequenciais) sem incluir registros redundantes. Por redundante, quero dizer registros que podem ser implícitos em outros registros.

Por exemplo, se o preço ontem foi $ 1 e o preço hoje é $ 1, e não houve outras mudanças de preço entre ontem e hoje, então o preço hoje pode ser inferido a partir do preço ontem sem armazenar um preço para ambos os dias.

Aqui está o cenário que estou tentando resolver. Temos uma tabela de preços históricos dos itens. Novos preços são importados periodicamente para a tabela. O arquivo de importação pode conter datas de qualquer época, não sabemos se elas estão sempre "depois" dos dados na tabela de histórico.

Para evitar o inchaço dos dados, só quero inserir registros se eles fornecerem novas informações. Portanto, se um novo registro puder ser inferido de um registro antigo, não desejo inserir o novo registro e, se um registro antigo puder ser inferido de um novo registro, desejo remover o registro antigo e inserir o novo registro.

Alguns exemplos concretos podem ajudar, aqui estão os dois cenários de problemas:

  1. Um registro de entrada pode ser inferido de um registro existente, portanto, o registro de entrada é redundante. Por exemplo

    recorde antigo: 23/04/2013 1,00

    novo registro: 2013-04-24 1.00 <-- isso está implícito no registro existente, não o insira

  2. Um registro existente pode ser inferido de um novo registro, portanto, o registro existente é redundante. Por exemplo

    novo recorde: 2013-04-23 1,00

    registro antigo: 2013-04-24 1.00 <-- isso está implícito no novo registro, exclua-o

  3. Isso apenas mostra um exemplo de quando um valor não é redundante. Por exemplo

    recorde antigo: 23/04/2013 1,00

    recorde antigo: 2013-04-24 1.20

    novo recorde: 2013-04-25 1,00 <-- não redundante, o preço mudou desde o último 1,00

Há um exemplo mais detalhado aqui http://sqlfiddle.com/#!3/2ef87/2

Atualmente, estou inclinado para uma abordagem de várias etapas de:

  1. Excluir da entrada onde houver um registro existente que tenha o mesmo preço com uma data anterior (cenário 1 acima).
  2. Excluir de existente onde houver um registro de entrada que tenha o mesmo preço com uma data anterior (cenário 2 acima).
  3. Insira os registros de entrada restantes.

Deve haver uma maneira melhor, talvez usando MERGE, mas está me dando trabalho tentando descobrir como fazê-lo.

Como faço para "mesclar" com eficiência os registros existentes e recebidos? Obrigado

sql-server sql-server-2008
  • 3 respostas
  • 2742 Views
Martin Hope
WileCau
Asked: 2013-05-21 00:04:07 +0800 CST

Existe uma maneira padrão de usar dados e procedimentos comuns em vários bancos de dados?

  • 3

Temos vários bancos de dados independentes que têm dados e códigos em comum, não no sentido de serem acessados ​​entre os bancos de dados, mas no sentido de que os dados significam a mesma coisa em cada banco de dados e o código faz a mesma coisa.

Exemplos são:

  • Definições de configuração (por exemplo, códigos de erro 50xxx, texto clichê para o nome da empresa, etc.).
  • Procedimentos e funções que executam tarefas comuns (por exemplo, converter uma string CSV em uma tabela, registrar um erro, formatar uma mensagem de erro com base no código de erro).
  • Estruturas de tabela (por exemplo, tabela para histórico de versão do banco de dados, tabela para registro de erros). Além das colunas, restrições e gatilhos, também existem procedimentos e funções comuns que leem/gravam os dados.
  • Tabelas de consulta (por exemplo, tabela de consulta de datas contendo datas entre 2000-2100). Elas são semelhantes às estruturas de tabela, mas frequentemente os dados serão os mesmos nos bancos de dados. No caso da tabela de datas, as datas de início e término são parâmetros de configuração, que são lidos por uma função, depois os dados de data são gerados por um procedimento. Todas essas operações são comuns entre os bancos de dados.
  • Tipos definidos pelo usuário (por exemplo, tipos para passar tabelas para funções).

Por motivos de manutenção e suporte, acho que faz sentido que coisas como códigos de erro, procedimentos, funções e tipos tenham um "ponto único de verdade" em todos os bancos de dados, não uma verdade diferente em cada banco de dados.

No momento, cada banco de dados tem sua própria cópia de tudo, incluindo o repositório de origem, e nós os mantemos de forma independente. Isso está longe do ideal porque é muito fácil corrigir um procedimento em A e esquecer de colocá-lo em B, ou adicionar um código de erro a A e o mesmo a B, mas significam coisas diferentes, etc.

Os bancos de dados não são atualizados ao mesmo tempo e não residem necessariamente no mesmo hardware. Há casos em que eles podem ler dados um do outro (se o outro existir).

Existe uma maneira padrão de ter um único ponto de verdade para dados/código usado em mais de um banco de dados?

sql-server sql-server-2008
  • 2 respostas
  • 1511 Views
Martin Hope
WileCau
Asked: 2013-05-17 05:02:48 +0800 CST

Como evitar o uso de variáveis ​​na cláusula WHERE

  • 16

Dado um procedimento armazenado (simplificado) como este:

CREATE PROCEDURE WeeklyProc(@endDate DATE)
AS
BEGIN
  DECLARE @startDate DATE = DATEADD(DAY, -6, @endDate)
  SELECT
    -- Stuff
  FROM Sale
  WHERE SaleDate BETWEEN @startDate AND @endDate
END

Se a Saletabela for grande SELECTpode levar muito tempo para executar, aparentemente porque o otimizador não pode otimizar devido à variável local. Testamos a execução da SELECTparte com variáveis, em seguida, codificamos as datas e o tempo de execução passou de ~ 9 minutos para ~ 1 segundo.

Temos vários procedimentos armazenados que consultam com base em intervalos de datas "fixos" (semana, mês, 8 semanas etc), de modo que o parâmetro de entrada é apenas @endDate e @startDate é calculado dentro do procedimento.

A questão é: qual é a melhor prática para evitar variáveis ​​em uma cláusula WHERE para não comprometer o otimizador?

As possibilidades que encontramos são mostradas abaixo. Algumas dessas práticas são recomendadas ou existe outra maneira?

Use um procedimento de wrapper para transformar as variáveis ​​em parâmetros.

Os parâmetros não afetam o otimizador da mesma forma que as variáveis ​​locais.

CREATE PROCEDURE WeeklyProc(@endDate DATE)
AS
BEGIN
   DECLARE @startDate DATE = DATEADD(DAY, -6, @endDate)
   EXECUTE DateRangeProc @startDate, @endDate
END

CREATE PROCEDURE DateRangeProc(@startDate DATE, @endDate DATE)
AS
BEGIN
  SELECT
    -- Stuff
  FROM Sale
  WHERE SaleDate BETWEEN @startDate AND @endDate
END

Use SQL dinâmico parametrizado.

CREATE PROCEDURE WeeklyProc(@endDate DATE)
AS
BEGIN
  DECLARE @startDate DATE = DATEADD(DAY, -6, @endDate)
  DECLARE @sql NVARCHAR(4000) = N'
    SELECT
      -- Stuff
    FROM Sale
    WHERE SaleDate BETWEEN @startDate AND @endDate
  '
  DECLARE @param NVARCHAR(4000) = N'@startDate DATE, @endDate DATE'
  EXECUTE sp_executesql @sql, @param, @startDate = @startDate, @endDate = @endDate
END

Use SQL dinâmico "hard-coded".

CREATE PROCEDURE WeeklyProc(@endDate DATE)
AS
BEGIN
  DECLARE @startDate DATE = DATEADD(DAY, -6, @endDate)
  DECLARE @sql NVARCHAR(4000) = N'
    SELECT
      -- Stuff
    FROM Sale
    WHERE SaleDate BETWEEN @startDate AND @endDate
  '
  SET @sql = REPLACE(@sql, '@startDate', CONVERT(NCHAR(10), @startDate, 126))
  SET @sql = REPLACE(@sql, '@endDate', CONVERT(NCHAR(10), @endDate, 126))
  EXECUTE sp_executesql @sql
END

Use a DATEADD()função diretamente.

Não estou interessado nisso porque chamar funções no WHERE também afeta o desempenho.

CREATE PROCEDURE WeeklyProc(@endDate DATE)
AS
BEGIN
  SELECT
    -- Stuff
  FROM Sale
  WHERE SaleDate BETWEEN DATEADD(DAY, -6, @endDate) AND @endDate
END

Use um parâmetro opcional.

Não tenho certeza se atribuir a parâmetros teria o mesmo problema que atribuir a variáveis, então isso pode não ser uma opção. Eu realmente não gosto desta solução, mas incluindo-a para completar.

CREATE PROCEDURE WeeklyProc(@endDate DATE, @startDate DATE = NULL)
AS
BEGIN
  SET @startDate = DATEADD(DAY, -6, @endDate)
  SELECT
    -- Stuff
  FROM Sale
  WHERE SaleDate BETWEEN @startDate AND @endDate
END

-- Atualizar --

Obrigado pelas sugestões e comentários. Depois de lê-los, fiz alguns testes de tempo com as várias abordagens. Estou adicionando os resultados aqui como referência.

A execução 1 é sem um plano. A execução 2 é imediatamente após a execução 1 com exatamente os mesmos parâmetros, de modo que usará o plano da execução 1.

Os horários NoProc são para executar as consultas SELECT manualmente no SSMS fora de um procedimento armazenado.

TestProc1-7 são as consultas da pergunta original.

TestProcA-B são baseados na sugestão de Mikael Eriksson . A coluna no banco de dados é uma DATE, então tentei passar o parâmetro como DATETIME e executar com conversão implícita (testProcA) e conversão explícita (testProcB).

TestProcC-D são baseados na sugestão de Kenneth Fisher . Já usamos uma tabela de pesquisa de datas para outras coisas, mas não temos uma com uma coluna específica para cada período. A variação que tentei ainda usa BETWEEN, mas faz isso na tabela de pesquisa menor e se une à tabela maior. Vou investigar mais a fundo se podemos usar tabelas de pesquisa específicas, embora nossos períodos sejam fixos, existem alguns diferentes.

    Total de linhas na tabela Venda: 136.424.366

                       Executar 1 (ms) Executar 2 (ms)
    Procedimento CPU decorrido CPU decorrido Comentário
    Constantes NoProc 6567 62199 2870 719 Consulta manual com constantes
    Variáveis ​​NoProc 9314 62424 3993 998 Consulta manual com variáveis
    testProc1 6801 62919 2871 736 Faixa codificada
    testProc2 8955 63190 3915 979 Parâmetro e faixa variável
    testProc3 8985 63152 3932 987 Procedimento de wrapper com intervalo de parâmetros
    testProc4 9142 63939 3931 977 SQL dinâmico parametrizado
    testProc5 7269 62933 2933 728 SQL dinâmico codificado
    testProc6 9266 63421 3915 984 Use DATEADD em DATE
    testProc7 2044 13950 1092 1087 Parâmetro fictício
    testProcA 12120 61493 5491 1875 Use DATEADD em DATETIME sem CAST
    testProcB 8612 61949 3932 978 Use DATEADD em DATETIME com CAST
    testProcC 8861 61651 3917 993 Use a tabela de pesquisa, Venda primeiro
    testProcD 8625 61740 3994 1031 Use a tabela de pesquisa, Última venda

Aqui está o código de teste.

------ SETUP ------

IF OBJECT_ID(N'testDimDate', N'U') IS NOT NULL DROP TABLE testDimDate
IF OBJECT_ID(N'testProc1', N'P') IS NOT NULL DROP PROCEDURE testProc1
IF OBJECT_ID(N'testProc2', N'P') IS NOT NULL DROP PROCEDURE testProc2
IF OBJECT_ID(N'testProc3', N'P') IS NOT NULL DROP PROCEDURE testProc3
IF OBJECT_ID(N'testProc3a', N'P') IS NOT NULL DROP PROCEDURE testProc3a
IF OBJECT_ID(N'testProc4', N'P') IS NOT NULL DROP PROCEDURE testProc4
IF OBJECT_ID(N'testProc5', N'P') IS NOT NULL DROP PROCEDURE testProc5
IF OBJECT_ID(N'testProc6', N'P') IS NOT NULL DROP PROCEDURE testProc6
IF OBJECT_ID(N'testProc7', N'P') IS NOT NULL DROP PROCEDURE testProc7
IF OBJECT_ID(N'testProcA', N'P') IS NOT NULL DROP PROCEDURE testProcA
IF OBJECT_ID(N'testProcB', N'P') IS NOT NULL DROP PROCEDURE testProcB
IF OBJECT_ID(N'testProcC', N'P') IS NOT NULL DROP PROCEDURE testProcC
IF OBJECT_ID(N'testProcD', N'P') IS NOT NULL DROP PROCEDURE testProcD
GO

CREATE TABLE testDimDate
(
   DateKey DATE NOT NULL,
   CONSTRAINT PK_DimDate_DateKey UNIQUE NONCLUSTERED (DateKey ASC)
)
GO

DECLARE @dateTimeStart DATETIME = '2000-01-01'
DECLARE @dateTimeEnd DATETIME = '2100-01-01'
;WITH CTE AS
(
   --Anchor member defined
   SELECT @dateTimeStart FullDate
   UNION ALL
   --Recursive member defined referencing CTE
   SELECT FullDate + 1 FROM CTE WHERE FullDate + 1 <= @dateTimeEnd
)
SELECT
   CAST(FullDate AS DATE) AS DateKey
INTO #DimDate
FROM CTE
OPTION (MAXRECURSION 0)

INSERT INTO testDimDate (DateKey)
SELECT DateKey FROM #DimDate ORDER BY DateKey ASC

DROP TABLE #DimDate
GO

-- Hard coded date range.
CREATE PROCEDURE testProc1 AS
BEGIN
   SET NOCOUNT ON
   SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN '2012-12-09' AND '2012-12-10'
END
GO

-- Parameter and variable date range.
CREATE PROCEDURE testProc2(@endDate DATE) AS
BEGIN
   SET NOCOUNT ON
   DECLARE @startDate DATE = DATEADD(DAY, -1, @endDate)
   SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN @startDate AND @endDate
END
GO

-- Parameter date range.
CREATE PROCEDURE testProc3a(@startDate DATE, @endDate DATE) AS
BEGIN
   SET NOCOUNT ON
   SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN @startDate AND @endDate
END
GO

-- Wrapper procedure.
CREATE PROCEDURE testProc3(@endDate DATE) AS
BEGIN
   SET NOCOUNT ON
   DECLARE @startDate DATE = DATEADD(DAY, -1, @endDate)
   EXEC testProc3a @startDate, @endDate
END
GO

-- Parameterized dynamic SQL.
CREATE PROCEDURE testProc4(@endDate DATE) AS
BEGIN
   SET NOCOUNT ON
   DECLARE @startDate DATE = DATEADD(DAY, -1, @endDate)
   DECLARE @sql NVARCHAR(4000) = N'SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN @startDate AND @endDate'
   DECLARE @param NVARCHAR(4000) = N'@startDate DATE, @endDate DATE'
   EXEC sp_executesql @sql, @param, @startDate = @startDate, @endDate = @endDate
END
GO

-- Hard coded dynamic SQL.
CREATE PROCEDURE testProc5(@endDate DATE) AS
BEGIN
   SET NOCOUNT ON
   DECLARE @startDate DATE = DATEADD(DAY, -1, @endDate)
   DECLARE @sql NVARCHAR(4000) = N'SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN ''@startDate'' AND ''@endDate'''
   SET @sql = REPLACE(@sql, '@startDate', CONVERT(NCHAR(10), @startDate, 126))
   SET @sql = REPLACE(@sql, '@endDate', CONVERT(NCHAR(10), @endDate, 126))
   EXEC sp_executesql @sql
END
GO

-- Explicitly use DATEADD on a DATE.
CREATE PROCEDURE testProc6(@endDate DATE) AS
BEGIN
   SET NOCOUNT ON
   SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN DATEADD(DAY, -1, @endDate) AND @endDate
END
GO

-- Dummy parameter.
CREATE PROCEDURE testProc7(@endDate DATE, @startDate DATE = NULL) AS
BEGIN
   SET NOCOUNT ON
   SET @startDate = DATEADD(DAY, -1, @endDate)
   SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN @startDate AND @endDate
END
GO

-- Explicitly use DATEADD on a DATETIME with implicit CAST for comparison with SaleDate.
-- Based on the answer from Mikael Eriksson.
CREATE PROCEDURE testProcA(@endDateTime DATETIME) AS
BEGIN
   SET NOCOUNT ON
   SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN DATEADD(DAY, -1, @endDateTime) AND @endDateTime
END
GO

-- Explicitly use DATEADD on a DATETIME but CAST to DATE for comparison with SaleDate.
-- Based on the answer from Mikael Eriksson.
CREATE PROCEDURE testProcB(@endDateTime DATETIME) AS
BEGIN
   SET NOCOUNT ON
   SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN CAST(DATEADD(DAY, -1, @endDateTime) AS DATE) AND CAST(@endDateTime AS DATE)
END
GO

-- Use a date lookup table, Sale first.
-- Based on the answer from Kenneth Fisher.
CREATE PROCEDURE testProcC(@endDate DATE) AS
BEGIN
   SET NOCOUNT ON
   DECLARE @startDate DATE = DATEADD(DAY, -1, @endDate)
   SELECT SUM(Value) FROM Sale J INNER JOIN testDimDate D ON D.DateKey = J.SaleDate WHERE D.DateKey BETWEEN @startDate AND @endDate
END
GO

-- Use a date lookup table, Sale last.
-- Based on the answer from Kenneth Fisher.
CREATE PROCEDURE testProcD(@endDate DATE) AS
BEGIN
   SET NOCOUNT ON
   DECLARE @startDate DATE = DATEADD(DAY, -1, @endDate)
   SELECT SUM(Value) FROM testDimDate D INNER JOIN Sale J ON J.SaleDate = D.DateKey WHERE D.DateKey BETWEEN @startDate AND @endDate
END
GO

------ TEST ------

SET STATISTICS TIME OFF

DECLARE @endDate DATE = '2012-12-10'
DECLARE @startDate DATE = DATEADD(DAY, -1, @endDate)

DBCC FREEPROCCACHE WITH NO_INFOMSGS
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS

RAISERROR('Run 1: NoProc with constants', 0, 0) WITH NOWAIT
SET STATISTICS TIME ON
SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN '2012-12-09' AND '2012-12-10'
SET STATISTICS TIME OFF

RAISERROR('Run 2: NoProc with constants', 0, 0) WITH NOWAIT
SET STATISTICS TIME ON
SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN '2012-12-09' AND '2012-12-10'
SET STATISTICS TIME OFF

DBCC FREEPROCCACHE WITH NO_INFOMSGS
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS

RAISERROR('Run 1: NoProc with variables', 0, 0) WITH NOWAIT
SET STATISTICS TIME ON
SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN @startDate AND @endDate
SET STATISTICS TIME OFF

RAISERROR('Run 2: NoProc with variables', 0, 0) WITH NOWAIT
SET STATISTICS TIME ON
SELECT SUM(Value) FROM Sale WHERE SaleDate BETWEEN @startDate AND @endDate
SET STATISTICS TIME OFF

DECLARE @sql NVARCHAR(4000)

DECLARE _cursor CURSOR LOCAL FAST_FORWARD FOR
   SELECT
      procedures.name,
      procedures.object_id
   FROM sys.procedures
   WHERE procedures.name LIKE 'testProc_'
   ORDER BY procedures.name ASC

OPEN _cursor

DECLARE @name SYSNAME
DECLARE @object_id INT

FETCH NEXT FROM _cursor INTO @name, @object_id
WHILE @@FETCH_STATUS = 0
BEGIN
   SET @sql = CASE (SELECT COUNT(*) FROM sys.parameters WHERE object_id = @object_id)
      WHEN 0 THEN @name
      WHEN 1 THEN @name + ' ''@endDate'''
      WHEN 2 THEN @name + ' ''@startDate'', ''@endDate'''
   END

   SET @sql = REPLACE(@sql, '@name', @name)
   SET @sql = REPLACE(@sql, '@startDate', CONVERT(NVARCHAR(10), @startDate, 126))
   SET @sql = REPLACE(@sql, '@endDate', CONVERT(NVARCHAR(10), @endDate, 126))

   DBCC FREEPROCCACHE WITH NO_INFOMSGS
   DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS

   RAISERROR('Run 1: %s', 0, 0, @sql) WITH NOWAIT
   SET STATISTICS TIME ON
   EXEC sp_executesql @sql
   SET STATISTICS TIME OFF

   RAISERROR('Run 2: %s', 0, 0, @sql) WITH NOWAIT
   SET STATISTICS TIME ON
   EXEC sp_executesql @sql
   SET STATISTICS TIME OFF

   FETCH NEXT FROM _cursor INTO @name, @object_id
END

CLOSE _cursor
DEALLOCATE _cursor
sql-server sql-server-2008
  • 3 respostas
  • 31205 Views

Sidebar

Stats

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

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

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

    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
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • 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
    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