PostgreSQL的存储过程简单入门
2012-10-15 08:22
260 查看
一、存储过程结构:
Createorreplacefunction过程名(参数名参数类型,…..)returns返回值类型as
$body$
//声明变量
Declare
变量名变量类型;
如:
flagBoolean;
变量赋值方式(变量名类型:=值;)
如:
strtext:=值;/strtext;str:=值;
Begin
函数体;
return变量名;//存储过程中的返回语句
End;
$body$
Languageplpgsql;
二、变量类型:
除了postgresql内置的变量类型外,常用的还有RECORD,表示一条记录。
整数数据类型:
浮点数据类型:(浮点数据也可以再细分,分为提供通用功能的浮点值和固定精度的数字)
注:
存储float和real类型的数据的行为非常相似,但是numeric列的行为有点不同。Numeric类型不是存储接近的数,而是在小数后面进行后超出固定长度的部分进行四舍五入。如果我们存储太大的数据到其中,INSERT将失败。还要注意float和real也会对数字四舍五入;例如123.456789被四舍五入为123.457。
时间数据类型:
特殊数据类型:
注:PostgreSQL也允许你使用SQL命令CREATE
TYPE在数据库中建立你自己的类型。这通常不需要,而且在一定程度上,它是PostgreSQL独有的。
数组
通常,一个数组需要通过使用一个附加表实现。但是,数组的能力有时候很有用。建立数组的方法有两种:传统的PostgreSQL的方法和SQL99标准的方法。
PostgreSQL样式的数组
test=>CREATETABLEempworkday(
test(>refcodechar(5),
test(>workdaysint[]
test(>);
往数组列中插入值:
test=>INSERTINTOempworkdayVALUES(‘val01′,‘{0,1,0,1,1,1,1}’);
test=>INSERTINTOempworkdayVALUES(‘val02′,‘{0,1,1,1,1,0,1}’);
SQL99样式的数字
在SQL99标准中,必须指出元素的个数。
Eg:
test=>CREATETABLEempworkday(
test(>refcodechar(5),
test(>workdaysintarray[7]
test(>);
test=>INSERTINTOempworkdayVALUES(‘val01′,‘{0,1,0,1,1,1,1}’);
test=>INSERTINTOempworkdayVALUES(‘val02′,‘{0,1,1,1,1,0,1}’);
三、连接字符:
Postgresql存储过程中的连接字符不再是“+”,而是使用“||”。
四、控制结构:
1、if条件(五种形式)
IF...THEN
IF...THEN...ELSE
IF...THEN...ELSEIF
IF...THEN...ELSIF...THEN...ELSE
IF...THEN...ELSEIF...THEN...ELSE(注:ELSEIF是ELSIF的别名)
2、循环
使用LOOP,EXIT,CONTINUE,WHILE,和FOR语句,可以控制PL/pgSQL函数重复一系列命令。
1)、LOOP
LOOP定义一个无条件的循环,无限循环,直到由EXIT或者RETURN语句终止。可选的label可以由EXIT和CONTINUE语句使用,用于在嵌套循环中声明应该应用于哪一层循环。
2)、EXIT
如果声明了WHEN,循环退出只有在expression为真的时候才发生,否则控制会落到EXIT后面的语句上。
EXIT可以用于在所有的循环类型中,它并不仅仅限制于在无条件循环中使用。在和BEGIN块一起使用的时候,EXIT把控制交给块结束后的下一个语句。
例如:
Loop循环
If…then条件判断
Exit;条件成立,则退出循环。
Endif;
Endloop;
3)、CONTINUE
CONTINUE[label][WHENexpression];
如果没有给出label,那么就开始最内层的循环的下一次执行。也就是说,控制传递回给循环控制表达式(如果有),然后重新计算循环体。如果出现了label,它声明即将继续执行的循环的标签。
如果声明了WHEN,那么循环的下一次执行只有在expression为真的情况下才进行。否则,控制传递给CONTINUE后面的语句。
CONTINUE可以用于所有类型的循环;它并不仅仅限于无条件循环。
例如:
这种形式的FOR对一定范围的整数数值进行迭代的循环。变量name会自动定义为integer类型并且只在循环里存在。给出范围上下界的两个表达式在进入循环的时候计算一次。迭代步进值总是为1,但如果声明了REVERSE就是-1。
一些整数FOR循环的例子∶
如果下界大于上界(或者是在REVERSE情况下是小于),那么循环体将完全不被执行。而且不会抛出任何错误。
3、异常捕获
EXCEPTION
WHEN错误码(如:STRING_DATA_RIGHT_TRUNCATION:字串数据右边被截断)THEN
/**后台打印错误信息*/
RAISENOTICE'错吴信息';
五、示例代码:
/**
批量插入一批数据,经纬度字段值要满足中国地理位置上的经纬度范围;
注:时间不能指定为同一时间,否则会扫描全表,导致性能低下。下列脚本未考虑时间的分段,采用的一个时间点。
*/
createorreplacefunctionintobatch()returnsintegeras
$body$
declare
skyidinteger;
lotfloat;
latfloat;
sexvarchar;
levelinteger;
ctimeint:=1325404914;
numinteger:=0;
totalinteger:=0;
begin
lot='73.6666666';
lat='3.8666666';
FORskyidIN404499817..404953416loop
if(lot>135.0416666)then
lot=73.6666666;
endif;
if(lat>53.5500000)then
lat=3.8666666;
endif;
if(skyid%2<>0)then
sex='1';
level=0;
else
sex='2';
level=1;
endif;
INSERTINTOuser_last_location(user_id,app_id,lonlat,sex,accurate_level,lonlat_point,create_time)
VALUES(skyid,2934,ST_GeomFromText('POINT('||lot||''||lat||')',4326),sex,level,POINT(lot,lat),to_timestamp(ctime));
lot=lot+0.1;
lat=lat+0.1;
skyid=skyid+1;
endloop;
returnskyid;
end
$body$
languageplpgsql;
SELECT*fromintobatch();
Createorreplacefunction过程名(参数名参数类型,…..)returns返回值类型as
$body$
//声明变量
Declare
变量名变量类型;
如:
flagBoolean;
变量赋值方式(变量名类型:=值;)
如:
strtext:=值;/strtext;str:=值;
Begin
函数体;
return变量名;//存储过程中的返回语句
End;
$body$
Languageplpgsql;
二、变量类型:
除了postgresql内置的变量类型外,常用的还有RECORD,表示一条记录。
整数数据类型:
子类型 | 标准名 | 描述 |
Smalllinteger | Smallint | 一个2字节的符号型整数,可以存储-32768到32767的数字 |
Integer | Int | 一个4字节的符号型整数,可以存储-2147483648到2147473647的数字 |
Serial | 和integer一样,除了它的值通常是由PostgreSQL自动输入的。 |
子类型 | 标准名 | 描述 |
float | float(n) | 支持最少精度为n,存储为最多8字节的浮点数。 |
float8 | real | 双精度(8字节)浮点数字 |
numeric | numeric(p,s) | 拥有p个数字的实数,其中小数点后有s位。不像float,这始终是一个确切的数字,但工作效率比普通浮点数字低。 |
money | numeric(9,2) | PostgreSQL特有的类型,但在其他数据库里也普遍存在。Money类型从PostgreSQL8.0开始不赞成使用,且可能在以后版本中取消。你应该使用number类型代替。 |
存储float和real类型的数据的行为非常相似,但是numeric列的行为有点不同。Numeric类型不是存储接近的数,而是在小数后面进行后超出固定长度的部分进行四舍五入。如果我们存储太大的数据到其中,INSERT将失败。还要注意float和real也会对数字四舍五入;例如123.456789被四舍五入为123.457。
时间数据类型:
定义 | 意义 |
date | 存储日期信息 |
time | 存储时间信息 |
timestamp | 存储日期和时间 |
interval | 存储timestamp之间差别的信息 |
timestamptz | PostgreSQL扩展的类型,存储包含时区信息的timestamp |
定义 | 意义 |
box | 矩形盒子 |
line | 一组点 |
point | 一对几何学的数字 |
lseg | 一条线段 |
polygon | 一条封闭的几何线 |
cidr或inet | 一个IPv4的地址,录入192.168.0.1 |
macaddr | 以MAC地址(以太网卡物理地址) |
TYPE在数据库中建立你自己的类型。这通常不需要,而且在一定程度上,它是PostgreSQL独有的。
数组
通常,一个数组需要通过使用一个附加表实现。但是,数组的能力有时候很有用。建立数组的方法有两种:传统的PostgreSQL的方法和SQL99标准的方法。
PostgreSQL样式的数组
要将一个表的列定义为数组,你可以简单地在类型后面添加[];不需要定义元素的个数。即使定义了个数,也不会强制要求存储的个数。
Eg:test=>CREATETABLEempworkday(
test(>refcodechar(5),
test(>workdaysint[]
test(>);
往数组列中插入值:
test=>INSERTINTOempworkdayVALUES(‘val01′,‘{0,1,0,1,1,1,1}’);
test=>INSERTINTOempworkdayVALUES(‘val02′,‘{0,1,1,1,1,0,1}’);
SQL99样式的数字
在SQL99标准中,必须指出元素的个数。
Eg:
test=>CREATETABLEempworkday(
test(>refcodechar(5),
test(>workdaysintarray[7]
test(>);
test=>INSERTINTOempworkdayVALUES(‘val01′,‘{0,1,0,1,1,1,1}’);
test=>INSERTINTOempworkdayVALUES(‘val02′,‘{0,1,1,1,1,0,1}’);
三、连接字符:
Postgresql存储过程中的连接字符不再是“+”,而是使用“||”。
四、控制结构:
1、if条件(五种形式)
IF...THEN
IF...THEN...ELSE
IF...THEN...ELSEIF
IF...THEN...ELSIF...THEN...ELSE
IF...THEN...ELSEIF...THEN...ELSE(注:ELSEIF是ELSIF的别名)
2、循环
使用LOOP,EXIT,CONTINUE,WHILE,和FOR语句,可以控制PL/pgSQL函数重复一系列命令。
1)、LOOP
[<<label>>]
LOOP
statements
ENDLOOP[label];
LOOP定义一个无条件的循环,无限循环,直到由EXIT或者RETURN语句终止。可选的label可以由EXIT和CONTINUE语句使用,用于在嵌套循环中声明应该应用于哪一层循环。
2)、EXIT
EXIT[label][WHENexpression];
如果没有给出label,那么退出最内层的循环,然后执行跟在ENDLOOP后面的语句。如果给出label,那么它必须是当前或者更高层的嵌套循环块或者语句块的标签。然后该命名块或者循环就会终止,而控制落到对应循环/块的END语句后面的语句上。
如果声明了WHEN,循环退出只有在expression为真的时候才发生,否则控制会落到EXIT后面的语句上。
EXIT可以用于在所有的循环类型中,它并不仅仅限制于在无条件循环中使用。在和BEGIN块一起使用的时候,EXIT把控制交给块结束后的下一个语句。
例如:
Loop循环
If…then条件判断
Exit;条件成立,则退出循环。
Endif;
Endloop;
3)、CONTINUE
CONTINUE[label][WHENexpression];
如果没有给出label,那么就开始最内层的循环的下一次执行。也就是说,控制传递回给循环控制表达式(如果有),然后重新计算循环体。如果出现了label,它声明即将继续执行的循环的标签。
如果声明了WHEN,那么循环的下一次执行只有在expression为真的情况下才进行。否则,控制传递给CONTINUE后面的语句。
CONTINUE可以用于所有类型的循环;它并不仅仅限于无条件循环。
例如:
LOOP
一些计算
EXITWHENcount>100;
CONTINUEWHENcount<50;
一些在count数值在[50..100]里面时候的计算
ENDLOOP;
4)、WHILE
[<<label>>]
WHILEexpressionLOOP
statements
ENDLOOP[label];
只要条件表达式为真,WHILE语句就会不停在一系列语句上进行循环.条件是在每次进入循环体的时候检查的.
例如:
WHILEamount_owed>0ANDgift_certificate_balance>0LOOP
--可以在这里做些计算
ENDLOOP;
WHILENOTBOOLEAN_expressionLOOP
--可以在这里做些计算
ENDLOOP;
5)、FOR(整数变种)
[<<label>>]
FORnameIN[REVERSE]expression..expressionLOOP
statements
ENDLOOP[labal];
这种形式的FOR对一定范围的整数数值进行迭代的循环。变量name会自动定义为integer类型并且只在循环里存在。给出范围上下界的两个表达式在进入循环的时候计算一次。迭代步进值总是为1,但如果声明了REVERSE就是-1。
一些整数FOR循环的例子∶
FORiIN1..10LOOP表示1循环到10
这里可以放一些表达式
RAISENOTICE'iIS%',i;
ENDLOOP;
FORiINREVERSE10..1LOOP
这里可以放一些表达式
ENDLOOP;
如果下界大于上界(或者是在REVERSE情况下是小于),那么循环体将完全不被执行。而且不会抛出任何错误。
3、异常捕获
EXCEPTION
WHEN错误码(如:STRING_DATA_RIGHT_TRUNCATION:字串数据右边被截断)THEN
/**后台打印错误信息*/
RAISENOTICE'错吴信息';
五、示例代码:
/**
批量插入一批数据,经纬度字段值要满足中国地理位置上的经纬度范围;
注:时间不能指定为同一时间,否则会扫描全表,导致性能低下。下列脚本未考虑时间的分段,采用的一个时间点。
*/
createorreplacefunctionintobatch()returnsintegeras
$body$
declare
skyidinteger;
lotfloat;
latfloat;
sexvarchar;
levelinteger;
ctimeint:=1325404914;
numinteger:=0;
totalinteger:=0;
begin
lot='73.6666666';
lat='3.8666666';
FORskyidIN404499817..404953416loop
if(lot>135.0416666)then
lot=73.6666666;
endif;
if(lat>53.5500000)then
lat=3.8666666;
endif;
if(skyid%2<>0)then
sex='1';
level=0;
else
sex='2';
level=1;
endif;
INSERTINTOuser_last_location(user_id,app_id,lonlat,sex,accurate_level,lonlat_point,create_time)
VALUES(skyid,2934,ST_GeomFromText('POINT('||lot||''||lat||')',4326),sex,level,POINT(lot,lat),to_timestamp(ctime));
lot=lot+0.1;
lat=lat+0.1;
skyid=skyid+1;
endloop;
returnskyid;
end
$body$
languageplpgsql;
SELECT*fromintobatch();
相关文章推荐
- PostgreSQL的存储过程简单入门
- PostgreSQL的存储过程简单入门
- PostgreSQL9.3 存储过程与触发器入门
- C#调用存储过程的方法,和简单存储过程创建的方法实例。【转载】为入门的朋友引路,大家互相学习。
- ASP.NET 2.0 新手SQL存储过程简单实例入门 绝对经典入门
- SqlServer存储过程之简单入门
- ASP.NET 2.0 新手SQL存储过程简单实例入门。绝对经典入门
- PostgreSQL存储过程简单示例
- ASP.NET 2.0 新手SQL存储过程简单实例入门 绝对经典入门
- SqlServer存储过程之简单入门
- SqlServer存储过程之简单入门
- SQL 存储过程简单入门
- 一个简单的oracle分页存储过程的实现和调用
- PostgreSQL 数据操作入门,简单对比MySQL
- mysql存储过程实战基础入门
- 一个简单存储过程的性能分析
- 数据仓库--postgresql for 循环记录完成存储过程总调度
- mysql 存储过程加事务的简单写法
- 关于存储过程中一个参数表示多个查询条件使用方法的简单处理
- postgresql 写存储过程传入的参数为字符串('4,5,6,8,9,10')个数不确定时,如何一次性删除