PHP - MSSQL 从存储过程中获取结果

3
我是一名老派的开发者,刚进入万维网编程世界。我正在使用HTML、CSS、PHP和MSSQL Server 2008 R2为我所在公司开发一个应用程序。
在我的应用程序中,我使用存储过程来插入、修改、删除或查询数据。我完全不使用TSQL指令,只是从PHP代码中执行存储过程。
我使用PHP 5和SQLSRV驱动程序进行数据库交互。
到目前为止,一切都很顺利,但现在我卡在了插入部分......如果一切正常,存储过程会插入记录,如果不行,就不会......但是除非我再次查询表格以查看记录是否存在,否则我看不到结果。
我在PHP中使用以下代码来运行插入记录的存储过程:
function spinserta($tabla, $columnas, $valores, $cnct) {

   $stmt = 'Exec spinsert @tabla=?,@columnas=?,@valores=?';         
   $params = array($tabla,$columnas,$valores);

   $result = sqlsrv_query($cnct,$stmt,$params) ;

   return $result;
}

如果交易不成功,$result变量中将得不到任何东西,我想要从存储过程中获取结果消息以便向用户显示错误消息。如何获得存储过程的结果消息(无论是否出现错误)?谢谢!
2个回答

2
这是我应用程序中的一些代码。看看它是否有所帮助:
//Query SQL
$tsql = "Exec spinsert @tabla=?,@columnas=?,@valores=?"; 
$params = array($tabla,$columnas,$valores);

//Execute the stored query 
$stmt = sqlsrv_query($conn, $tsql, $params);
if ($stmt === false)
{
    echo "<h3>Error in query preparation or execution.</h3>";
    ListErrors();
    die;
}
else {
    echo "Insert Successful";
}

// this should help for the non-insert/update case
$arr = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
var_dump($arr);

不起作用...我添加了以下IF语句,但结果始终为“失败!!!”。当我查询$result变量的值时,在成功或失败的情况下,它都包含“资源ID#14”。'function spinserta($tabla,$columnas,$valores,$cnct) { $stmt = 'Exec spinsert @tabla=?,@columnas=?,@valores=?';
$params = array($tabla,$columnas,$valores); $result = sqlsrv_query($cnct,$stmt,$params) ; if ($result==false) { echo "<h1>成功!!!</h1>"; } else { echo "<h1>失败!!!</h1>"; } echo "<br><h1>$result</h1><br>"; return $result; }'
- wamador
`function spinserta($tabla,$columnas,$valores,$cnct) { $stmt = 'Exec spinsert @tabla=?,@columnas=?,@valores=?';
$params = array($tabla,$columnas,$valores); $result = sqlsrv_query($cnct,$stmt,$params) ; if ($result==false) { echo "<h1>Success!!!</h1>"; } else { echo "<h1>Failure!!!</h1>"; } echo "<br><h1>$result</h1><br>"; return $result; }`
- wamador
你能否更新你的问题并附上这段代码,这样会更容易阅读。此外,你的存储过程在 PHP 代码之外是否正常工作? - Maximus2012
经过多次尝试,我找到了一种验证SP执行是否成功的方法:在语句执行后立即,在存储过程中捕获变量@@error,并将其作为SP的结果返回。在PHP函数方面,以下是实现方法:function spinserta($tabla,$columnas,$valores,$cnct) { $tsql = 'Exec spinsert @tabla=?,@columnas=?,@valores=?';
$params = array($tabla,$columnas,$valores); $stmt = sqlsrv_query($cnct,$tsql,$params) ; if ($stmt === false) { $stmt=0; } else { $stmt=1; } echo $stmt; return $stmt; }
- wamador
你能否编辑你的问题并添加这些额外的信息? - Maximus2012
显示剩余2条评论

1

经过数小时的研究......终于理解了!这就是问题所在:原始的PHP代码如下:

function spinserta($tabla, $columnas, $valores, $cnct) {
   $stmt = 'Exec spinsert @tabla=?,@columnas=?,@valores=?';         
   $params = array($tabla,$columnas,$valores);

   $result = sqlsrv_query($cnct,$stmt,$params) ;

   return $result;
}

原始SP是:

ALTER PROCEDURE [dbo].[spinsert] 
    @tabla varchar(50),
    @columnas varchar(8000),
    @valores varchar(8000)
AS
BEGIN
    SET NOCOUNT ON;
    declare @orden varchar(8000)
    declare @return_value int

    set @orden='Insert into ' + @tabla + ' (' + @columnas + ') values (' + @valores + ')';
    execute (@orden);

    return 
END

非常简单...当php代码执行并且存储过程成功时,变量$result将会被加载为"Resource id#14",如果存储过程失败,则$result的值为null。
一切都运作得很好!!!但不是我想要的方式。然后我发现了这篇文章:http://msdn.microsoft.com/en-us/library/ms178592.aspx 基于此,我修改了存储过程:
ALTER PROCEDURE [dbo].[spinsert] 
    @tabla varchar(50),
    @columnas varchar(8000),
    @valores varchar(8000)
AS
BEGIN
    SET NOCOUNT ON;
    declare @orden varchar(8000)
    declare @return_value int

    begin try
        set @orden='Insert into ' + @tabla + ' (' + @columnas + ') values (' + @valores + ')';
        set @return_value=0;
        execute (@orden);
    end try

    begin catch
        DECLARE @ErrorMessage NVARCHAR(4000);
        DECLARE @ErrorSeverity INT;
        DECLARE @ErrorState INT;

        SELECT @return_value = ERROR_NUMBER()
        SELECT 
            @ErrorMessage = ERROR_MESSAGE(),
            @ErrorSeverity = ERROR_SEVERITY(),
            @ErrorState = ERROR_STATE();

        RAISERROR (@ErrorMessage, -- Message text.
                   @ErrorSeverity, -- Severity.
                   @ErrorState -- State.
                   );
    end catch

    return @return_value

END

以及PHP代码:

function spinserta($tabla,$columnas,$valores,$cnct) {
    $tsql = 'Exec spinsert @tabla=?,@columnas=?,@valores=?';            
    $params = array($tabla,$columnas,$valores);

    $stmt = sqlsrv_query($cnct,$tsql,$params) ; 
    $errors=sqlsrv_errors();

    if ($stmt === false or $stmt===0) {
        foreach( $errors as $error ) {
            $stmt=str_replace("'","","Error: ". $error['code']. " - " . $error['message']);
            }
    } else {
        $stmt="1";
    }       

    return $stmt;
}

我的原始方法存在两个问题,一个是在数据库引擎方面,存储过程实际上没有生成系统错误,即使语句失败了。通过使用Try-Catch技术和RAISEERROR概念,当语句失败时,存储过程最终生成了系统错误。之后,只需要对PHP代码进行微调即可。
采用这种方法,将信息验证发送到数据库,在数据库引擎端完成,消除了编写大量代码以验证提交时间表单字段的需要。所需的是确保数据库表、关系、约束、完整性等得到良好应用,数据库将保护自身免受不正确的数据影响。如果提交的表单信息存在错误,则数据库将拒绝它们,代码将向用户显示相应错误。
我想看看是否可以使用MySQL做类似的事情......我认为是可以的!
非常感谢Maximus2012!!!干杯!!!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接