如何在java / jsp中执行MS SQL Server存储过程,返回表数据?

| 我很难从Java / jsp执行MS SQL Server存储过程。我希望返回一个表数据集;存储过程的最后一行是来自表的常规select语句。 (从这一点来看,执行存储过程的时间是“ 0”。) 我查看了以下网站以寻求帮助: www.2netave.com www.stackoverflow.com 我没有意识到只为存储过程提供功能,因为我使用的是
createStatement()
。 现在,请了解存储过程在SQL Server Management Studio中可以完美执行,并且我在使用
createStatement()
在jsp / java中执行临时查询没有问题。 我创建了一个不带参数的简单存储过程,只是为了缩小问题范围:
CREATE PROCEDURE sp_test AS
BEGIN
PRINT \'HELLO WORLD\'
END
这是我的jsp页面中的代码:
Class.forName(\"net.sourceforge.jtds.jdbc.Driver\");
java.sql.Connection conn = java.sql.DriverManager.getConnection(\"jdbc:jtds:sqlserver://MySQLServer:1433/test\", \"user\", \"pass\");
java.sql.CallableStatement cs = conn.prepareCall(\"{call sp_test}\"); 
java.sql.ResultSet ResultSet = cs.execute();
浏览器告诉我,由于发生内部服务器错误,因此无法显示该页面。我知道这意味着上面的代码有问题。 我尝试了这个:
java.sql.ResultSet ResultSet = cs.executeQuery();
还有这个:
java.sql.CallableStatement cs = conn.prepareCall(\"{execute sp_test}\");
还有这个:
java.sql.CallableStatement cs = conn.prepareCall(\"{exec sp_test}\");
没有任何效果。一旦可以正常工作,就可以运行实际的存储过程,该存储过程从select语句返回表数据。但是我什至无法使这个虚拟存储过程正常工作。 我在这里做错了什么? 谢谢。 更新: 检查服务器日志(IIS)和我的HTTP代理fiddler,并且不报告任何内容。但是,IIS使用tomcat作为jsp页面的servlet引擎。并且tomcat日志文件报告以下内容:
An error occurred at line: 20 in the jsp file: /test.jsp
Type mismatch: cannot convert from boolean to ResultSet
17: 
18:     java.sql.CallableStatement cs = conn.prepareCall(\"{call sp_test}\");
19:     
20:     java.sql.ResultSet ResultSet = cs.execute();
21: 
22: //  java.sql.ResultSet ResultSet = state.executeQuery(SQL); 
23: 
我尝试将以上内容更改为:
cs.execute();
并且日志文件报告:
- Servlet.service() for servlet jsp threw exception
java.sql.SQLException: The EXECUTE permission was denied on the object \'sp_test\', database \'test\', schema \'dbo\'.
所以,我想我必须向用户支付11英镑。另一个问题是从存储过程返回表数据。 如果我有这样的程序:
CREATE PROCEDURE sp_test2 AS
BEGIN
SELECT * FROM TABLE
END
如何在jsp中操作表格数据?与存储过程相反,
ResultSet
是否只适用于即席查询,而存储过程则使用,1ѭ来执行查询? 谢谢。 更新2: 解: 为了操作表数据,我必须使用以下命令:
java.sql.ResultSet RS = cs.executeQuery();
它在ѭ16上失败,并且在命名
ResultSet
对象\“ ResultSet \”时失败。过去,它从来没有抱怨过“ 1”。但是由于某种原因,对于存储过程,它不喜欢这种命名约定。 谢谢。     
已邀请:
我们的服务器像这样从Java调用存储的proc-在SQL Server 2000和2008上均可使用:
String SPsql = \"EXEC <sp_name> ?,?\";   // for stored proc taking 2 parameters
Connection con = SmartPoolFactory.getConnection();   // java.sql.Connection
PreparedStatement ps = con.prepareStatement(SPsql);
ps.setEscapeProcessing(true);
ps.setQueryTimeout(<timeout value>);
ps.setString(1, <param1>);
ps.setString(2, <param2>);
ResultSet rs = ps.executeQuery();
    
感谢Brian提供的代码。我试图用
{call spname(?,?)}
连接到sql服务器,但出现错误,但是当我将代码更改为
exec sp...
时,它工作得很好。 我发布我的代码,希望这可以帮助其他人解决我的问题:
ResultSet rs = null;
PreparedStatement cs=null;
Connection conn=getJNDIConnection();

try {
    cs=conn.prepareStatement(\"exec sp_name ?,?,?,?,?,?,?\");
    cs.setEscapeProcessing(true);
    cs.setQueryTimeout(90);

    cs.setString(1, \"valueA\");

    cs.setString(2, \"valueB\");

    cs.setString(3, \"0418\");

    //commented, because no need to register parameters out!, I got results from the resultset. 
    //cs.registerOutParameter(1, Types.VARCHAR);
    //cs.registerOutParameter(2, Types.VARCHAR);

    rs = cs.executeQuery();
    ArrayList<ObjectX> listaObjectX = new ArrayList<ObjectX>();
    while (rs.next()) {

        ObjectX to = new ObjectX();
        to.setFecha(rs.getString(1));
        to.setRefId(rs.getString(2));
        to.setRefNombre(rs.getString(3));
        to.setUrl(rs.getString(4));

        listaObjectX.add(to);

    }
    return listaObjectX;
     } catch (SQLException se) {
        System.out.println(\"Error al ejecutar SQL\"+ se.getMessage());
        se.printStackTrace();
        throw new IllegalArgumentException(\"Error al ejecutar SQL: \" + se.getMessage());

    } finally {

        try {

            rs.close();
            cs.close();
          con.close();

        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
    
通常,我们会与其他创建这些存储过程的Java程序员一起工作。 而且我们不想弄乱它。 但是有可能在这些exec样本返回0(几乎存储过程调用返回零)的地方得到结果集。 检查这个样本:
public void generateINOUT(String USER, int DPTID){

    try {


        conUrl = JdbcUrls + dbServers +\";databaseName=\"+ dbSrcNames+\";instance=MSSQLSERVER\";

        con = DriverManager.getConnection(conUrl,dbUserNames,dbPasswords);
        //stat = con.createStatement();
        con.setAutoCommit(false); 
        Statement st = con.createStatement(); 

        st.executeUpdate(\"DECLARE @RC int\\n\" +
                \"DECLARE @pUserID nvarchar(50)\\n\" +
                \"DECLARE @pDepartmentID int\\n\" +
                \"DECLARE @pStartDateTime datetime\\n\" +
                \"DECLARE @pEndDateTime datetime\\n\" +
                \"EXECUTE [AccessManager].[dbo].[SP_GenerateInOutDetailReportSimple] \\n\" +
                \"\"+USER +
                \",\" +DPTID+
                \",\'\"+STARTDATE +
                \"\',\'\"+ENDDATE+\"\'\");

        ResultSet rs = st.getGeneratedKeys();

        while (rs.next()){
              String userID = rs.getString(\"UserID\");
              Timestamp timeIN = rs.getTimestamp(\"timeIN\");
              Timestamp timeOUT = rs.getTimestamp (\"timeOUT\");
              int totTime = rs.getInt (\"totalTime\");
              int pivot = rs.getInt (\"pivotvalue\");

              timeINS = sdz.format(timeIN);
              userIN.add(timeINS);

              timeOUTS = sdz.format(timeOUT);
              userOUT.add(timeOUTS);

              System.out.println(\"User : \"+userID+\" |IN : \"+timeIN+\" |OUT : \"+timeOUT+\"| Total Time : \"+totTime+\" | PivotValue : \"+pivot);
        }

        con.commit();

    }catch (Exception e) {
        e.printStackTrace();
        System.out.println(e);
        if (e.getCause() != null) {
        e.getCause().printStackTrace();}
    }  
}
经过几天的尝试和错误,谷歌搜索并感到困惑;) 它在存储过程下面执行:
USE [AccessManager]
GO
/****** Object:  StoredProcedure [dbo].[SP_GenerateInOutDetailReportSimple]    
Script Date: 04/05/2013 15:54:11 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO


ALTER PROCEDURE [dbo].[SP_GenerateInOutDetailReportSimple]
(
@pUserID nvarchar(50),
@pDepartmentID int,
@pStartDateTime datetime,
@pEndDateTime datetime
)
AS


Declare @ErrorCode int
Select @ErrorCode = @@Error

Declare @TransactionCountOnEntry int
If @ErrorCode = 0
Begin
    Select @TransactionCountOnEntry = @@TranCount
    BEGIN TRANSACTION
End


If @ErrorCode = 0
Begin       

    -- Create table variable instead of SQL temp table because report wont pick up the temp table
    DECLARE @tempInOutDetailReport TABLE
    (
        UserID nvarchar(50),
        LogDate datetime,   
        LogDay varchar(20), 
        TimeIN datetime,
        TimeOUT datetime,
        TotalTime int,
        RemarkTimeIn nvarchar(100),
        RemarkTimeOut nvarchar(100),
        TerminalIPTimeIn varchar(50),
        TerminalIPTimeOut varchar(50),
        TerminalSNTimeIn nvarchar(50),
        TerminalSNTimeOut nvarchar(50),
        PivotValue int
    )           

    -- Declare variables for the while loop
    Declare @LogUserID nvarchar(50)
    Declare @LogEventID nvarchar(50)
    Declare @LogTerminalSN nvarchar(50)
    Declare @LogTerminalIP nvarchar(50)
    Declare @LogRemark nvarchar(50)
    Declare @LogTimestamp datetime  
    Declare @LogDay nvarchar(20)

    -- Filter off userID, departmentID, StartDate and EndDate if specified, only process the remaining logs
    -- Note: order by user then timestamp
    Declare LogCursor Cursor For 
    Select distinct access_event_logs.USERID, access_event_logs.EVENTID, 
        access_event_logs.TERMINALSN, access_event_logs.TERMINALIP,
        access_event_logs.REMARKS, access_event_logs.LOCALTIMESTAMP, Datename(dw,access_event_logs.LOCALTIMESTAMP) AS WkDay
    From access_event_logs
        Left Join access_user on access_user.User_ID = access_event_logs.USERID
        Left Join access_user_dept on access_user.User_ID = access_user_dept.User_ID
    Where ((Dept_ID = @pDepartmentID) OR (@pDepartmentID IS NULL))
        And ((access_event_logs.USERID LIKE \'%\' + @pUserID + \'%\') OR (@pUserID IS NULL)) 
        And ((access_event_logs.LOCALTIMESTAMP >= @pStartDateTime ) OR (@pStartDateTime IS NULL)) 
        And ((access_event_logs.LOCALTIMESTAMP < DATEADD(day, 1, @pEndDateTime) ) OR (@pEndDateTime IS NULL)) 
        And (access_event_logs.USERID != \'UNKNOWN USER\') -- Ignore UNKNOWN USER
    Order by access_event_logs.USERID, access_event_logs.LOCALTIMESTAMP

    Open LogCursor

    Fetch Next 
    From LogCursor
    Into @LogUserID, @LogEventID, @LogTerminalSN, @LogTerminalIP, @LogRemark, @LogTimestamp, @LogDay

    -- Temp storage for IN event details
    Declare @InEventUserID nvarchar(50)
    Declare @InEventDay nvarchar(20)
    Declare @InEventTimestamp datetime
    Declare @InEventRemark nvarchar(100)
    Declare @InEventTerminalIP nvarchar(50)
    Declare @InEventTerminalSN nvarchar(50)

    -- Temp storage for OUT event details
    Declare @OutEventUserID nvarchar(50)        
    Declare @OutEventTimestamp datetime
    Declare @OutEventRemark nvarchar(100)
    Declare @OutEventTerminalIP nvarchar(50)
    Declare @OutEventTerminalSN nvarchar(50)

    Declare @CurrentUser varchar(50) -- used to indicate when we change user group
    Declare @CurrentDay varchar(50) -- used to indicate when we change day
    Declare @FirstEvent int -- indicate the first event we received     
    Declare @ReceiveInEvent int -- indicate we have received an IN event
    Declare @PivotValue int -- everytime we change user or day - we reset it (reporting purpose), if same user..keep increment its value
    Declare @CurrTrigger varchar(50) -- used to keep track of the event of the current event log trigger it is handling 
    Declare @CurrTotalHours int -- used to keep track of total hours of the day of the user

    Declare @FirstInEvent datetime
    Declare @FirstInRemark nvarchar(100)
    Declare @FirstInTerminalIP nvarchar(50)
    Declare @FirstInTerminalSN nvarchar(50)
    Declare @FirstRecord int -- indicate another day of same user

    Set @PivotValue = 0 -- initialised
    Set @CurrentUser = \'\' -- initialised
    Set @FirstEvent = 1 -- initialised
    Set @ReceiveInEvent = 0 -- initialised  
    Set @CurrTrigger = \'\' -- Initialised    
    Set @CurrTotalHours = 0 -- initialised
    Set @FirstRecord = 1 -- initialised
    Set @CurrentDay = \'\' -- initialised

    While @@FETCH_STATUS = 0
    Begin
        -- use to track current log trigger
        Set @CurrTrigger =LOWER(@LogEventID)

        If (@CurrentUser != \'\' And @CurrentUser != @LogUserID) -- new batch of user
        Begin
            If @ReceiveInEvent = 1  -- previous IN event is not cleared (no OUT is found)
            Begin
                -- Check day
                If (@CurrentDay != @InEventDay) -- change to another day                    
                    Set @PivotValue = 0 -- Reset                        

                Else -- same day
                    Set @PivotValue = @PivotValue + 1 -- increment
                Set @CurrentDay = @InEventDay -- update the day

                -- invalid row (only has IN event)
                Insert into @tempInOutDetailReport( UserID, LogDay, TimeIN, RemarkTimeIn, TerminalIPTimeIn, 
                    TerminalSNTimeIn, PivotValue, LogDate )
                values( @InEventUserID, @InEventDay, @InEventTimestamp, @InEventRemark, @InEventTerminalIP, 
                    @InEventTerminalSN, @PivotValue, DATEADD(HOUR, 0, DATEDIFF(DAY, 0, @InEventTimestamp)))                                                         
            End                 

            Set @FirstEvent = 1 -- Reset flag (we are having a new user group)
            Set @ReceiveInEvent = 0 -- Reset
            Set @PivotValue = 0 -- Reset
            --Set @CurrentDay = \'\' -- Reset
        End

        If LOWER(@LogEventID) = \'in\' -- IN event
        Begin           
            If @ReceiveInEvent = 1  -- previous IN event is not cleared (no OUT is found)
            Begin
                -- Check day
                If (@CurrentDay != @InEventDay) -- change to another day
                Begin
                    Set @PivotValue = 0 -- Reset

                    --Insert into @tempInOutDetailReport( UserID, LogDay, TimeIN, TimeOUT, TotalTime, RemarkTimeIn,
                    --  RemarkTimeOut, TerminalIPTimeIn, TerminalIPTimeOut, TerminalSNTimeIn, TerminalSNTimeOut, PivotValue,
                    --  LogDate)
                    --values( @LogUserID, @CurrentDay, @FirstInEvent, @LogTimestamp,  @CurrTotalHours,
                    --  @FirstInRemark, @LogRemark, @FirstInTerminalIP, @LogTerminalIP, @FirstInTerminalSN, @LogTerminalSN, @PivotValue,
                    --  DATEADD(HOUR, 0, DATEDIFF(DAY, 0, @InEventTimestamp)))  
                End
                Else
                    Set @PivotValue = @PivotValue + 1 -- increment
                Set @CurrentDay = @InEventDay -- update the day


                -- invalid row (only has IN event)
                Insert into @tempInOutDetailReport( UserID, LogDay, TimeIN, RemarkTimeIn, TerminalIPTimeIn, 
                    TerminalSNTimeIn, PivotValue, LogDate )
                values( @InEventUserID, @InEventDay, @InEventTimestamp, @InEventRemark, @InEventTerminalIP, 
                    @InEventTerminalSN, @PivotValue, DATEADD(HOUR, 0, DATEDIFF(DAY, 0, @InEventTimestamp)))                     
            End         

            If((@CurrentDay != @LogDay And @CurrentDay != \'\') Or (@CurrentUser != @LogUserID And @CurrentUser != \'\') )
            Begin

                    Insert into @tempInOutDetailReport( UserID, LogDay, TimeIN, TimeOUT, TotalTime, RemarkTimeIn,
                        RemarkTimeOut, TerminalIPTimeIn, TerminalIPTimeOut, TerminalSNTimeIn, TerminalSNTimeOut, PivotValue,
                        LogDate)
                    values( @CurrentUser, @CurrentDay, @FirstInEvent, @OutEventTimestamp, @CurrTotalHours,
                        @FirstInRemark, @OutEventRemark, @FirstInTerminalIP, @OutEventTerminalIP, @FirstInTerminalSN, @LogTerminalSN, @PivotValue,
                        DATEADD(HOUR, 0, DATEDIFF(DAY, 0, @InEventTimestamp)))      

                Set @FirstRecord = 1
            End
            -- Save it
            Set @InEventUserID = @LogUserID                         
            Set @InEventDay = @LogDay
            Set @InEventTimestamp = @LogTimeStamp
            Set @InEventRemark = @LogRemark
            Set @InEventTerminalIP = @LogTerminalIP
            Set @InEventTerminalSN = @LogTerminalSN

            If (@FirstRecord = 1) -- save for first in event record of the day
            Begin
                Set @FirstInEvent = @LogTimestamp
                Set @FirstInRemark = @LogRemark
                Set @FirstInTerminalIP = @LogTerminalIP
                Set @FirstInTerminalSN = @LogTerminalSN
                Set @CurrTotalHours = 0 --initialise total hours for another day
            End

            Set @FirstRecord = 0 -- no more first record of the day
            Set @ReceiveInEvent = 1 -- indicate we have received an \"IN\" event
            Set @FirstEvent = 0  -- no more \"first\" event
        End
        Else If LOWER(@LogEventID) = \'out\' -- OUT event
        Begin
            If @FirstEvent = 1 -- the first OUT record when change users 
            Begin
                -- Check day
                If (@CurrentDay != @LogDay) -- change to another day
                    Set @PivotValue = 0 -- Reset
                Else
                    Set @PivotValue = @PivotValue + 1 -- increment
                Set @CurrentDay = @LogDay -- update the day

                -- Only an OUT event (no IN event) - invalid record but we show it anyway
                Insert into @tempInOutDetailReport( UserID, LogDay, TimeOUT, RemarkTimeOut, TerminalIPTimeOut, TerminalSNTimeOut,
                    PivotValue, LogDate )
                values( @LogUserID, @LogDay, @LogTimestamp, @LogRemark, @LogTerminalIP, @LogTerminalSN, @PivotValue,
                    DATEADD(HOUR, 0, DATEDIFF(DAY, 0, @LogTimestamp)))                                              

                Set @FirstEvent = 0 -- not \"first\" anymore
            End
            Else -- Not first event
            Begin       

                If @ReceiveInEvent = 1 -- if there are IN event previously
                Begin           
                    -- Check day
                    If (@CurrentDay != @InEventDay) -- change to another day                        
                        Set @PivotValue = 0 -- Reset                        
                    Else
                        Set @PivotValue = @PivotValue + 1 -- increment
                    Set @CurrentDay = @InEventDay -- update the day     
                    Set @CurrTotalHours = @CurrTotalHours +  DATEDIFF(second,@InEventTimestamp, @LogTimeStamp) -- update total time             

                    Set @OutEventRemark = @LogRemark
                    Set @OutEventTerminalIP = @LogTerminalIP
                    Set @OutEventTerminalSN = @LogTerminalSN
                    Set @OutEventTimestamp = @LogTimestamp          
                    -- valid row
                    --Insert into @tempInOutDetailReport( UserID, LogDay, TimeIN, TimeOUT, TotalTime, RemarkTimeIn,
                    --  RemarkTimeOut, TerminalIPTimeIn, TerminalIPTimeOut, TerminalSNTimeIn, TerminalSNTimeOut, PivotValue,
                    --  LogDate)
                    --values( @LogUserID, @InEventDay, @InEventTimestamp, @LogTimestamp,  Datediff(second, @InEventTimestamp, @LogTimeStamp),
                    --  @InEventRemark, @LogRemark, @InEventTerminalIP, @LogTerminalIP, @InEventTerminalSN, @LogTerminalSN, @PivotValue,
                    --  DATEADD(HOUR, 0, DATEDIFF(DAY, 0, @InEventTimestamp)))                      

                    Set @ReceiveInEvent = 0 -- Reset
                End
                Else -- no IN event previously
                Begin
                    -- Check day
                    If (@CurrentDay != @LogDay) -- change to another day
                        Set @PivotValue = 0 -- Reset
                    Else
                        Set @PivotValue = @PivotValue + 1 -- increment
                    Set @CurrentDay = @LogDay -- update the day                         

                    -- invalid row (only has OUT event)
                    Insert into @tempInOutDetailReport( UserID, LogDay, TimeOUT, RemarkTimeOut, TerminalIPTimeOut, TerminalSNTimeOut,
                        PivotValue, LogDate )
                    values( @LogUserID, @LogDay, @LogTimestamp, @LogRemark, @LogTerminalIP, @LogTerminalSN, @PivotValue,
                        DATEADD(HOUR, 0, DATEDIFF(DAY, 0, @LogTimestamp)) )             
                End             
            End         
        End

        Set @CurrentUser = @LogUserID -- update user        

        Fetch Next 
        From LogCursor
        Into @LogUserID, @LogEventID, @LogTerminalSN, @LogTerminalIP, @LogRemark, @LogTimestamp, @LogDay
    End 

    -- Need to handle the last log if its IN log as it will not be processed by the while loop
    if @CurrTrigger=\'in\'
    Begin 
    -- Check day
            If (@CurrentDay != @InEventDay) -- change to another day
                Set @PivotValue = 0 -- Reset
            Else -- same day
                Set @PivotValue = @PivotValue + 1 -- increment
            Set @CurrentDay = @InEventDay -- update the day

            -- invalid row (only has IN event)
            Insert into @tempInOutDetailReport( UserID, LogDay, TimeIN, RemarkTimeIn, TerminalIPTimeIn, 
                TerminalSNTimeIn, PivotValue, LogDate )
            values( @InEventUserID, @InEventDay, @InEventTimestamp, @InEventRemark, @InEventTerminalIP, 
                    @InEventTerminalSN, @PivotValue, DATEADD(HOUR, 0, DATEDIFF(DAY, 0, @InEventTimestamp)))     
    End
    else if @CurrTrigger = \'out\'
    Begin
        Insert into @tempInOutDetailReport( UserID, LogDay, TimeIN, TimeOUT, TotalTime, RemarkTimeIn,
        RemarkTimeOut, TerminalIPTimeIn, TerminalIPTimeOut, TerminalSNTimeIn, TerminalSNTimeOut, PivotValue,
        LogDate)
        values( @LogUserID, @CurrentDay, @FirstInEvent, @LogTimestamp,  @CurrTotalHours,
        @FirstInRemark, @LogRemark, @FirstInTerminalIP, @LogTerminalIP, @FirstInTerminalSN, @LogTerminalSN, @PivotValue,
        DATEADD(HOUR, 0, DATEDIFF(DAY, 0, @InEventTimestamp)))  
    End

    Close LogCursor
    Deallocate LogCursor

    Select * 
    From @tempInOutDetailReport tempTable
        Left Join access_user on access_user.User_ID = tempTable.UserID
    Order By tempTable.UserID, LogDate


End



If @@TranCount > @TransactionCountOnEntry
Begin
     If @ErrorCode = 0
            COMMIT TRANSACTION
     Else
            ROLLBACK TRANSACTION
End

return @ErrorCode
右键单击数据库中的存储过程,将获得\“ java SQL Code \”。 像这样的东西:
DECLARE @RC int
DECLARE @pUserID nvarchar(50)
DECLARE @pDepartmentID int
DECLARE @pStartDateTime datetime
DECLARE @pEndDateTime datetime

-- TODO: Set parameter values here.

EXECUTE @RC = [AccessManager].[dbo].[SP_GenerateInOutDetailReportSimple] 
@pUserID,@pDepartmentID,@pStartDateTime,@pEndDateTime
GO
检查我完成的查询字符串,这是您的作业;) 很抱歉回答了这么久, 自从我几周前注册以获得答案以来,这是我的第一个答案。     
FWIW,sp_test将不返回任何值,而是一个整数(所有SQL Server存储的proc只返回一个整数),并且线路上没有结果集(因为没有SELECT语句)。若要获取PRINT语句的输出,通常在ADO.NET中对连接(而不是命令)使用InfoMessage事件。     

要回复问题请先登录注册