信息:
- PHP 7.0.0
- SQL Server 2014
- 使用sqlsrv驱动程序
以下代码可能不是最佳的,但这是PHP:
$nombre = strval($info->nombre);
$idPerfil = 0;
$sqlAltaPerfil = "{CALL AltaPerfil(?,?)}";
$paramsAltaPerfil = [
[$nombre, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_VARCHAR(50)],
[&$idPerfil, SQLSRV_PARAM_INOUT, SQLSRV_PHPTYPE_INT, SQLSRV_SQLTYPE_INT]
];
$stmtAltaPerfil = sqlsrv_query($conexion, $sqlAltaPerfil, $paramsAltaPerfil);
if($stmtAltaPerfil !== false) {
sqlsrv_next_result($stmtAltaPerfil);
$sqlAltaPerfilXExComp = "{CALL AltaPerfilXExamenComplementario(?, ?)}";
foreach($info->arrayIdExComp as $idExComp){
$idExComp = intval($idExComp);
var_dump($idExComp);
$paramsAltaPerfilXExComp = [
[$idPerfil, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_INT, SQLSRV_SQLTYPE_INT],
[$idExComp, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_INT, SQLSRV_SQLTYPE_INT]
];
$stmtAltaPerfilXExComp = sqlsrv_query($conexion, $sqlAltaPerfilXExComp, $paramsAltaPerfilXExComp);
if($stmtAltaPerfilXExComp !== false){
//bien
}
else{
$exito = false;
$erroresPhp .= print_r(sqlsrv_errors(), true);
break;
}
}
}
这是SP:
ALTER PROCEDURE [dbo].[AltaPerfil](
@Descripcion varchar(50),
@IdPerfil int OUTPUT
) AS
BEGIN
INSERT INTO PERFILEXAMENCOMPLEMENTARIO (Descripcion) VALUES (@Descripcion)
SET @IdPerfil = @@IDENTITY
RETURN
END
我从客户端显示的错误消息中知道$idPerfil
保持等于0(第2行(。有趣的是,在SSMS中,SP工作得很好,但当从PHP调用它时,$idPerfil
不会修改
编辑:我发现问题不在于代码,而是数据库中的一个触发器由于某种原因干扰了SP中的@@IDENTITY变量。
这就是触发:
ALTER TRIGGER [dbo].[NombresPerfilesUnicos] ON [dbo].[PERFILEXAMENCOMPLEMENTARIO] INSTEAD OF INSERT, UPDATE AS
BEGIN
DECLARE @NombrePerfil varchar(50)
SELECT @NombrePerfil = Descripcion FROM inserted
IF EXISTS(SELECT PEC.IdPerfil FROM PERFILEXAMENCOMPLEMENTARIO PEC WHERE Descripcion = @NombrePerfil)
PRINT 'ERROR, la descripcion ' + @NombrePerfil + ' ya esta registrada'
else
INSERT INTO PERFILEXAMENCOMPLEMENTARIO SELECT Descripcion FROM inserted
END
所以我的新问题是:为什么会发生这种情况?我必须做些什么才能保持这个触发器工作(如有必要进行修改(并使一切正常工作?
尝试使用SCOPE_IDENITY((而不是@@IDENTITY。
来源:http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/
">选择@@IDENTITY
它返回连接上生成的最后一个IDENTITY值,而不管生成该值的表是什么,也不管生成值的语句的作用域是什么">
">选择SCOPE_IDENITY((
它返回连接和同一范围内的语句生成的最后一个IDENTITY值,而不管生成该值的表是什么">
您可以按以下方式使用:如果存储过程中没有任何与第二个变量相关的事务,则不需要第二个。将IDENT_CURRENT与表名一起使用比其他表名要好得多,因为它只会返回所提到的表的标识值。
--程序部分
ALTER PROCEDURE [dbo].[AltaPerfil](
@Descripcion VARCHAR(50)
) AS
BEGIN
INSERT INTO PERFILEXAMENCOMPLEMENTARIO(Description) VALUES (@Descripcion)
SELECT IDENT_CURRENT('PERFILEXAMENCOMPLEMENTARIO') AS rowID
END
--从PHP调用替换为您的变量,它将返回值为的列rowID
EXEC AltaPerfil 'test'
最后,我所要做的就是将SET NOCOUNT ON
添加到SP中,它神奇地起到了的作用
ALTER PROCEDURE [dbo].[AltaPerfil](
@Descripcion varchar(50),
@IdPerfil int out
) AS
BEGIN
SET NOCOUNT ON;
INSERT INTO PERFILEXAMENCOMPLEMENTARIO (Descripcion) VALUES (@Descripcion)
SET @IdPerfil = @@IDENTITY
END