Mysql 的 function 和 procedure 有啥区别呢 ? 网上搜索后说 function 有返回值, procedure 无返回值。
从function 的语法角度来说确实如此, function 的定义中有 return 一项,如下所示
CREATE DEFINER=`root`@`%` FUNCTION `spr_checkadmin`(acckey varchar(32), accpwd varchar(64)) RETURNS int(11) BEGIN DECLARE x INT; SELECT COUNT(*) INTO x FROM admins WHERE account=acckey AND passwd=accpwd; RETURN(x); END;
然后再C语言中使用的时候我们可以 SELECT spr_checkadmin('acckey', 'accpwd') 来得到该返回值。
其实 procedure 也可以得到返回值, 且得到的方法有两种, 一种是通过类似function 的功能来得到返回值, 一种是通过输出参数的方式来得到返回值,比如有多个返回值的时候用输出参数的方式也很好。
杀猪杀尾巴, 各有各的方法。
下面通过返回值来调用存储过程:
CREATE DEFINER=`root`@`%` PROCEDURE `spr_getuserstorage`(tok varchar(128)) BEGIN DECLARE acc VARCHAR(32); DECLARE pkgid VARCHAR(32); DECLARE regdate DATETIME; DECLARE logindate DATETIME; DECLARE sumsize BIGINT; SELECT account INTO acc FROM userinfo WHERE token=tok; IF (acc != NULL) THEN SELECT SUM(filesize) INTO sumsize FROM userfiles WHERE account=acc; SELECT packageid, registerdate, lastlogindate INTO pkgid, regdate, logindate FROM userinfo WHERE account=acc; SELECT 0,pkgid,regdate,logindate; ELSE SELECT(-1); END IF;
看见上面代码中的 SELECT (-1) 或者 SELECT 0, pkgid,regdate,logindate 了吗 ?
这样的方式可以在记录集中返回一个值, 我们只要取到这个值即可。 效果与FUNCTION 中的 RETURN(-1) 是一样的。
下面介绍一下通过输出参数来实现多个输出的情况 :
CREATE DEFINER=`root`@`%` PROCEDURE `spr_queryfolderallfile`(sToken varchar(32), OUT sfid varchar(32), OUT sfext varchar(32)) BEGIN DECLARE acc CHAR(32); SELECT account INTO acc FROM userinfo WHERE token=sToken; IF (acc != NULL) THEN SELECT fileid, fileext INTO sfid, sfext FROM userfiles WHERE account=acc AND filetype=1; END IF; END;
通过C调用存储过程如下
strcpy(query,"call querystudent ('token',@fileid,@fileext)");
mysql_real_query (&mysql, query, strlen(query));
mysql_query(&mysql, "SELECT @fileid,@fileext");
这样在返回的记录集中就可以得到输出参数的值。
是不是很简单。
MYSQL 有很多内置的函数, 最常用的就是 ROW_COUNT() 取得影响的行数,
LAST_INSERT_ID() 返回最近一次插入的记录的自动增长的ID。
另外还需要注意, 要让MYSQL 的query 可以执行 存储过程, 需要把 mysql_real_connect 的最后一个参数设置为
CLIENT_MULTI_STATEMENTS, 否则会报错。
static int mysqlctx_connect(MYSQL_CTX* ctx, char *user,char *pwd,char *ip,char *db,unsigned short port) { unsigned int time_out = 5; mysql_options( &ctx->m_MySql, MYSQL_OPT_CONNECT_TIMEOUT, (char*)&time_out ); if( !mysql_real_connect(&ctx->m_MySql, ip, user, pwd, db, port, NULL, CLIENT_MULTI_STATEMENTS) ) { return -1; } //mysql_query( &ctx->m_MySql,"SET character_set_results = NULL" ); mysql_query( &ctx->m_MySql,"set names utf8" ); mysql_query( &ctx->m_MySql,"SET wait_timeout = 7*24*60*60" ); return 0; } int mysqlctx_init (MYSQL_CTX* ctx, char *user, char *pwd, char *ip, char *db, unsigned short port) { ctx->m_SqlResult = 0; ctx->m_rows = 0; mysql_init( &ctx->m_MySql ); ctx->m_MySql.reconnect = 1; return mysqlctx_connect (ctx, user, pwd, ip, db, port); } void mysqlctx_free (MYSQL_CTX* ctx) { if( ctx->m_SqlResult != 0 ) { mysql_free_result( ctx->m_SqlResult ); ctx->m_SqlResult = 0; } mysql_close( &ctx->m_MySql ); }
const char *mysqlctx_get_err_str(MYSQL_CTX* ctx) { return mysql_error( &ctx->m_MySql ); } char* mysqlctx_get_field_value(MYSQL_CTX* ctx, int i ) { return ctx->m_rows[i]; } int mysqlctx_get_value_length(MYSQL_CTX* ctx, int i ) { unsigned long *lengths = mysql_fetch_lengths( ctx->m_SqlResult ); return lengths[i]; } int mysqlctx_query(MYSQL_CTX* ctx, const char *Sql ) { if( ctx->m_SqlResult != 0 ) { mysql_free_result( ctx->m_SqlResult ); ctx->m_SqlResult = 0; ctx->m_rows = 0; } if( mysql_query(&ctx->m_MySql, Sql) != 0 ) { if( mysql_ping(&ctx->m_MySql) != 0 || //mysql_query(&ctx->m_MySql,"SET character_set_results = NULL") != 0 || mysql_query(&ctx->m_MySql,"set names utf8") != 0 || mysql_query(&ctx->m_MySql,"SET wait_timeout = 7*24*60*60") != 0 || mysql_query(&ctx->m_MySql,Sql) != 0 ) return -1; } if( (ctx->m_SqlResult=mysql_store_result(&ctx->m_MySql)) != 0 ) { } // return 1;//ctx->m_rows = mysql_fetch_row( ctx->m_SqlResult ); return 0; } int mysqlctx_record_over(MYSQL_CTX* ctx) { return ctx->m_rows == 0?1:0; } //改函数每次返回一个结果集中的一行,当返回NULL时,代表到行末尾,就是可以一行一行的遍历结果集 char **mysqlctx_get_fetch_row( MYSQL_CTX* ctx ) { //if (ctx->m_SqlResult == 0 || ctx->m_rows == 0 ) return 0; if (ctx->m_SqlResult == 0) return 0; return ctx->m_rows = mysql_fetch_row( ctx->m_SqlResult ); } //取得"数据集"的数目,只针对select语句 long mysqlctx_get_rs_count( MYSQL_CTX* ctx ) { if (ctx->m_SqlResult == NULL) return 0; long rs_num = (long)mysql_num_rows(ctx->m_SqlResult); return rs_num; } unsigned long mysqlctx_escape_string(MYSQL_CTX* ctx, char* to, char *from, int len ) { return mysql_real_escape_string(&ctx->m_MySql, to, from, len); //return mysql_escape_string( in,out,len ); }