【问题标题】:Calling Sqlserver stored procedure from JDBC,Java从 JDBC、Java 调用 Sqlserver 存储过程
【发布时间】:2015-04-17 14:23:34
【问题描述】:

我可以从 toad sql server 运行这个查询。

exec msp_FormBsBa_yeni 0,'20150101','20150131',5000,0,2,0,null,1,null,0

从我在 java 中的应用程序中,由于语句没有返回结果集,它产生了错误。我尝试了很多事情,但我无法解决它。感谢您的帮助。

    // Connection,Resultset ve PrepStatement Declaration
    Connection connection = null;
    PreparedStatement pstmt = null;
    ResultSet rsa = null;
    List<EntCari> listrows = new ArrayList<EntCari>();

    try {
        connection = ConnectionFactory.getConnection();

        CallableStatement callableStatement = connection
                .prepareCall("{call msp_FormBsBa_yeni(0,N'20150101',N'20150131',5000,0,2,0,null,1,null,0)}");

        rsa = callableStatement.executeQuery();

        // 2:resultset check
        if (!rsa.next()) {
            System.out.println("no data");
        } else {
            do {
                // System.out.println("data exists");
                // Statements
                EntCari row = new EntCari();
                row.setMusteriadi(rsa.getString("Unvan"));// rsa.getxxx("column")
                listrows.add(row);

            } while (rsa.next());
        }

        // 2---

    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        DbUtil.close(rsa);
        DbUtil.close(pstmt);
        DbUtil.close(connection);
    }

toad sql server 的结果如下所示。

Unvan |Ulkesi |VergiKimlikNo| TCKimlik否| BelgeSayisi|Toplam| CariKod

客户a | 052 | 19697583840 | 1 | 2323,00 | HT00084

客户 b | 052 | | 2 | 2111,00 | HT01022

存储过程如下(sp的一部分,很长)

/****** Object: Procedure [dbo].[msp_FormBsBa_yeni]   Script Date: 18.04.2015 13:43:44 ******/
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
CREATE PROCEDURE dbo.msp_FormBsBa_yeni
@vFirmaNo    as integer,
@IlkTarih    as datetime,
@SonTarih    as datetime,
@MinTutar    as float,
@Bs_Ba_tip   as bit,
@BirlestimeTuru as tinyint,
@SonradanMuhasebelesenSeriDahilEdilmesin_fl as bit,
@SonradanMuhasebelesenSeriStr nvarchar(MAX),
@Aylik_BsBa_fl as bit,
@PerakendeCariKodu AS nvarchar(25),
@EvrakDetayliRapor_fl as bit
AS
BEGIN  /*dbo.fn_GetByteParam(1048)=1 ÖTV stok maliyetine eklensinmi*/
Declare @otv_vergino as tinyint
set @otv_vergino = dbo.fn_GetByteParam(855) /*ÖTV vergi tipi*/
Declare @otv_kdv_orani as FLOAT
set @otv_kdv_orani = 0.0
if @otv_vergino between 1 and 10
set @otv_kdv_orani = dbo.fn_VergiYuzde(@otv_vergino)
Declare @kontrol_belge_tarihinden as integer
set @kontrol_belge_tarihinden = dbo.fn_GetByteParam(4173) /*BsBa_Kontrol_Belge_tarihinden_fl*/
if exists (select * from tempdb..sysobjects where name LIKE '#BsBaEvrakDetayliTablo%') Drop Table dbo.#BsBaEvrakDetayliTablo
select
TABLONO,
MIN(CHRECNO) AS CHRECNO,
CARI,
MAX(TARIH) AS TARIH,
TIP,
SERI,
SIRA,
MAX(CINS)AS CINS,
MAX(BELNO)AS BELNO,
MAX(BELTAR)AS BELTAR...

这是错误信息

com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not return a result set.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:171)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:394)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:340)
    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:4575)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1400)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:179)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:154)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:283) 

【问题讨论】:

    标签: java jdbc


    【解决方案1】:

    您不能在返回游标/ResultSet 的 Transact-SQL CallableStatement 上调用 executeQuery()。调用该过程的正确方法是:

    // You should really use bind variables here...
    CallableStatement call = connection
        .prepareCall("{call msp_FormBsBa_yeni(?, ?, ?, ...)}");
    call.setInt(1, ...);
    call.setString(2, ...);
    
    // This returns true if there are any remaining ResultSets to fetch
    if (call.execute()) {
        do {
            try (ResultSet rs = call.getResultSet()) {
                // Consume the result set here...
            }
        }
    
        // Move on to the next result set, if any
        while (call.getMoreResults());
    }
    

    如果您想要完全通用,您还必须检查Statement.getUpdateCount(),以防更新计数与您的过程中的结果集交织在一起。

    【讨论】:

      【解决方案2】:

      当我在数据库客户端(例如 SQL Server Management Studio)中执行查询时,会返回一个表。

      我的存储过程很长,有一些插入和更新语句。如果存储过程在最终选择之前执行任何插入或更新,则 JDBC(SQL Server 驱动程序)会与行数混淆(并且将引发语句未返回结果集的异常)。幸运的是,修复非常简单:我只需要在存储过程的开头添加 SET NOCOUNT ON 即可。所以我的代码看起来像:

      CREATE PROCEDURE dbo.msp_FormBsBa_yeni
      @vFirmaNo as integer,
      @IlkTarih as datetime,
      @SonTarih as datetime,
      @MinTutar as float,
      @Bs_Ba_tip as bit,
      @BirlestimeTuru as tinyint,
      @SonradanMuhasebelesenSeriDahilEdilmesin_fl as bit,
      @SonradanMuhasebelesenSeriStr nvarchar(MAX),
      @Aylik_BsBa_fl as bit,
      @PerakendeCariKodu AS nvarchar(25),
      @EvrakDetayliRapor_fl as bit
      AS
      BEGIN
        SET NOCOUNT ON
      

      非常感谢您的贡献

      【讨论】:

        【解决方案3】:

        这里有两种方法可以实现..

        String SPsql = "EXEC msp_FormBsBa_yeni ?,?,?";   // for stored proc taking 3 params
        Connection con = SmartPoolFactory.getConnection();   
        PreparedStatement ps = con.prepareStatement(SPsql);
        ps.setEscapeProcessing(true);
        ps.setQueryTimeout(<timeout value>);
        ps.setString(1, "val");
        ps.setString(2, "val";
        ps.setString(3, "val");
        ResultSet rs = ps.executeQuery();
        

        或使用 JDBC scape 语法

        CallableStatement cStmt = conn.prepareCall("{call msp_FormBsBa_yeni (?, ?, ?) }");
        cStmt.setString(1, "val");
        cStmt.setString(2, "val");
        cStmt.setString(3, "val");
        cStmt.registerOutParameter(4, Types.INTEGER); // register the output params 
        cStmt.registerOutParameter("inOutParam", Types.INTEGER); // or by param name
        

        更多详情请查看thisthis

        我希望这会有所帮助。

        【讨论】:

        • 我尝试了您提供的第一种方式,不幸的是结果相同。该语句不返回结果集
        • 对于第二种方式,它给出了语法错误,因为括号应该在第一种之前?字符,正如我所见,我的问题不需要使用 out 参数。
        • 能否分享一下SP调用的执行结果
        • 第二种方式的结果相同,感谢您的努力。
        猜你喜欢
        • 1970-01-01
        • 2015-05-28
        • 2016-05-03
        • 2021-02-11
        • 1970-01-01
        • 1970-01-01
        • 2012-01-27
        • 1970-01-01
        相关资源
        最近更新 更多