所以我最终决定开始学习如何使用存储过程,虽然我确实让它们正常工作,但我不确定我是否正确地做了 - 也就是说。 最佳方式。所以这就是我所拥有的。
三个程序:TryAddTag,CheckTagExists和AddTag。
TryAddTag是我在其他代码(例如PHP等)和其他两个过程之间的中间过程,所以这是被调用的过程。
的 TryAddTag
DELIMITER //
CREATE PROCEDURE TryAddTag(
IN tagName VARCHAR(255)
)
BEGIN
-- Check if tag already exists
CALL CheckTagExists(tagName, @doesTagExist);
-- If it does not exist, add it
IF @doesTagExist = FALSE THEN
CALL AddTag(tagName);
END IF;
END //
DELIMITER ;
的 AddTag
DELIMITER //
CREATE PROCEDURE AddTag(
IN tagName VARCHAR(255)
)
BEGIN
INSERT INTO
tags
VALUES(
NULL,
tagName
);
END //
DELIMITER ;
的 CheckTagExists
DELIMITER //
CREATE PROCEDURE CheckTagExists(
IN
tagName VARCHAR(255),
OUT
doesTagExist BOOL
)
BEGIN
-- Check if tag exists
SELECT
EXISTS(
SELECT
*
FROM
tags
WHERE
tags.NAME = tagName
)
INTO
doesTagExist;
END //
DELIMITER ;
我的问题源于此并使用@doesTagExist。
-- Check if tag already exists
CALL CheckTagExists(tagName, @doesTagExist);
使用这些变量之一的正确方法是什么?和/或,如何使用DECLARE变量在CheckAddTag中存储CheckTagExists的结果?
我期待的东西...
DECLARE doesTagExist BOOL;
SET doesTagExist = CheckTagExist('str');
...
或类似的......
答案 0 :(得分:10)
你的存储过程对我的喜好有点过度设计 - 保持简单:)
drop table if exists tags;
create table tags
(
tag_id int unsigned not null auto_increment primary key,
name varchar(255) unique not null
)
engine=innodb;
drop procedure if exists insert_tag;
delimiter #
create procedure insert_tag
(
in p_name varchar(255)
)
proc_main:begin
declare v_tag_id int unsigned default 0;
if exists (select 1 from tags where name = p_name) then
select -1 as tag_id, 'duplicate name' as msg; -- could use multiple out variables...i prefer this
leave proc_main;
end if;
insert into tags (name) values (p_name);
set v_tag_id = last_insert_id();
-- do stuff with v_tag_id...
-- return success
select v_tag_id as tag_id, 'OK' as msg;
end proc_main #
delimiter ;
<?php
ob_start();
try{
$conn = new mysqli("localhost", "foo_dbo", "pass", "foo_db", 3306);
$conn->autocommit(FALSE); // start transaction
// create the tag
$name = 'f00';
$sql = sprintf("call insert_tag('%s')", $conn->real_escape_string($name));
$result = $conn->query($sql);
$row = $result->fetch_array();
$result->close();
$conn->next_result();
$tagID = $row["tag_id"]; // new tag_id returned by sproc
if($tagID < 0) throw new exception($row["msg"]);
$conn->commit();
echo sprintf("tag %d created<br/>refresh me...", $tagID);
}
catch(exception $ex){
ob_clean();
//handle errors and rollback
$conn->rollback();
echo sprintf("oops error - %s<br/>", $ex->getMessage());
}
// finally
$conn->close();
ob_end_flush();
?>
答案 1 :(得分:2)
存储的PROCEDURES
可以返回结果集。 The last thing you SELECT
in a stored procedure is available as a resultset to the calling environment.。存储的FUNCTIONS
只能返回一个结果原语
您也可以将参数标记为INOUT
parameters。
答案 2 :(得分:1)
如果你想要这个:
DECLARE doesTagExist BOOL;
SET doesTagExist = CheckTagExist('str');
然后你应该使用函数:
DELIMITER //
CREATE FUNCTION CheckTagExists(
tagName VARCHAR(255)
)
BEGIN
DECLARE doesTagExist BOOL;
-- Check if tag exists
SELECT
EXISTS(
SELECT
*
FROM
tags
WHERE
tags.NAME = tagName
)
INTO
doesTagExist;
RETURN doesTagExist;
END //
DELIMITER ;
答案 3 :(得分:0)
DECLARE doesTagExist BOOL;
SET CheckTagExist('str',doesTagExist);
是使用存储过程执行此操作的正确方法。没有“常规”返回值。