【问题标题】:Select Count stored procedure with dynamic query not working correctly选择计数存储过程与动态查询无法正常工作
【发布时间】:2019-08-22 16:31:37
【问题描述】:

-我正在尝试执行一个应该返回计数结果的存储过程,但它给了我以下错误(它是葡萄牙语):

2019-04-01 10:13:49.215  WARN 7068 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 214, SQLState: S0002
2019-04-01 10:13:49.216 ERROR 7068 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper   : O procedimento espera o parâmetro '@statement' do tipo 'ntext/nchar/nvarchar'.

-我不太明白,因为我设置的唯一参数是表名,我正在传递我的存储库执行代码。

-这是我的存储过程:

ALTER PROCEDURE [dbo].[usp_verificarTabelaCadMov] (
    @NomeTabela VARCHAR(20)

)   
AS
BEGIN
    SET NOCOUNT ON;

Declare @Comando Varchar(1000)
Declare @Resultado INT;

Set @Comando = 'SELECT @Resultado = COUNT(*) FROM sysobjects WHERE nome = ' + QUOTENAME(@NomeTabela)

exec sp_executesql @Comando , N'@Resultado INT OUTPUT', @Resultado = @Resultado OUTPUT

SELECT @Resultado

END;

GO

-这是我在我的存储库中的执行:

@Query(value = "EXECUTE usp_verificarTabelaCadMov :tabela", nativeQuery = true)
public Integer verificarTabela(@Param("tabela") String tabela);

-在我的控制器中:

                    String tabela = ("M00"+(String.valueOf(Math.round(funcionario.getEmpresa().getCodigo())))+anoInicio+mesAtual);
                    if (eventoEspelhoPontoRepository.verificarTabela(tabela) > 1) {
                        registros.addAll(eventoEspelhoPontoRepository.findAllRegistrosByFuncionarioTableUnica(
                                tabela, dataInicioString, dataFimString, funcionario.getCracha()));
                    }

EDIT1 - 我在这里尝试做的是选择一行表,但有时有些表不存在,所以我试图验证表是否存在,如果存在,它应该从那个表中执行 Select *,否则,应该忽略。这是我发现的唯一方法,如果有人有更好的方法,请帮助我。

顺便说一句,这是我上面提到的选择,我尝试使用 IF EXISTS 子句验证表的存在,但它不起作用,我在主程序上不断收到错误 COULD NOT EXTRACT RESULT SET。

ALTER PROCEDURE [dbo].[usp_listarRegistrosMov]
    --PARÂMETROS
    @NomeTabela VARCHAR(20),
    @DataInicial VARCHAR(20),
    @DataFinal VARCHAR(20),
    @Cracha FLOAT

AS  

IF EXISTS(SELECT name FROM sysobjects WHERE name = @NomeTabela AND xtype = 'U')

BEGIN

Declare @Comando Varchar(1000)

Set @Comando = 'SELECT * FROM ' + @NomeTabela + ' WHERE mov_data BETWEEN ''' + @DataInicial + ''' AND ''' + @DataFinal + ''' AND mov_cracha = ' + CAST(@Cracha AS VARCHAR(50))

Exec(@Comando)

END



GO

编辑 2:我也尝试在同一个 sp 中使用 OBJECT_ID:

IF OBJECT_ID(@NomeTabela) IS NOT NULL

但总是报错:

2019-04-01 11:18:03.147  WARN 7068 --- [nio-8080-exec-8] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: null
2019-04-01 11:18:03.148 ERROR 7068 --- [nio-8080-exec-8] o.h.engine.jdbc.spi.SqlExceptionHelper   : The statement did not return a result set.

【问题讨论】:

  • 这确实看起来像 SQL Server 代码。你确定它在 MySQL 数据库上吗?
  • 抱歉打错标签了,没注意到
  • @Comando 应该是 NVARCHAR 类型,而不是 VARCHAR。
  • @Morten 设置 N' 后出现同样的错误

标签: java sql-server spring hibernate stored-procedures


【解决方案1】:

我会这样做:

ALTER PROCEDURE dbo.usp_verificarTabelaCadMov
(
  @NomeTabela VARCHAR(20)
)
AS
  BEGIN
    SET NOCOUNT ON;

    DECLARE @Comando NVARCHAR(1000);
    DECLARE @Resultado INT;

    SET @Resultado = -1

        -- Or set to NULL depending on how you would like to handle table existence in the application code;
        --SET @Resultado = NULL

    IF OBJECT_ID(QUOTENAME(@NomeTabela), 'U') IS NOT NULL
      BEGIN
        SET @Comando = N'SELECT @Resultado = COUNT(*) FROM ' + QUOTENAME(@NomeTabela);

        EXEC sys.sp_executesql
          @Comando
          , N'@Resultado INT OUTPUT'
          , @Resultado OUTPUT;
      END;

    SELECT @Resultado AS resultado;
  END;

所以根据你的选择如何处理表的存在,调用

EXEC dbo.usp_verificarTabelaCadMov @NomeTabela = 'thistabledoesNOTexist';

将返回 -1 或 NULL(参见存储的 proc 注释)和

EXEC dbo.usp_verificarTabelaCadMov @NomeTabela = 'thistableDOESexist';

将返回一个值 > -1。

【讨论】:

  • @NomeTabela 参数是我在 sysobjects 中验证存在的表
  • 我在您的原始代码中看到了这一点,但是就像我说的那样,我要做的是做同样的检查,但然后通过 IF OBJECT_ID(QUOTENAME(@NomeTabela), 'U') IS NOT NULL。据我了解您的代码,如果表存在,您主要对行数感兴趣?
  • 实际上只是检查表是否存在。如果不存在,它应该跳过 select 并跳过我的 List 上的 addAll,然后继续到下一个你得到的表?
【解决方案2】:

修复它,我必须:

1 - 将我的存储过程更改为:

ALTER PROCEDURE dbo.usp_verificarTabelaCadMov
      @NomeTabela VARCHAR(20)
AS
BEGIN
      SET NOCOUNT ON;

      DECLARE @Exists INT

      IF EXISTS(SELECT name
                        FROM sysobjects
                        WHERE name = @NomeTabela)
      BEGIN
            SET @Exists = 1
      END
      ELSE
      BEGIN
            SET @Exists = 0
      END

      RETURN @Exists
END

2 - 将我对 Repository 的调用更改为:

@Query(value = "Declare @Exists int "
        + "Exec @Exists = usp_verificarTabelaCadMov :tabela"
        + " Select @Exists", nativeQuery = true)

结果:正在检查表是否存在。

【讨论】:

    猜你喜欢
    • 2022-01-05
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    • 2013-08-13
    • 1970-01-01
    相关资源
    最近更新 更多