??xml version="1.0" encoding="utf-8" standalone="yes"?> 因oracle应用E序及其工具toad、PLSQL Developer{的部v很多,动辙要安装几癑օ的Oracle Client实在很烦?/p>
Instant client而够用。这里共享出自己的经验,供同行参考,如果能给你帮助,荣幸之至?/p>
q行环境Qwindows XP sp3Q新安装pȝQ从未安装过M版本Oracle 1、下载Instant Client http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html 扑ֈ与系l对应版本下载?/p>
q里?2位windowspȝQ?/p>
instantclient-basic-nt-11.2.0.3.0.zip instantclient-sqlplus-nt-11.2.0.3.0.zip 如果你只用客L工具Q不使用命o行下sqlplusQ第二个包可以不?/p>
2、解压羃包到C:\instantclient_11_2 3、设|变量: NLS_lANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBKQ注意中间有I格Q这个如果不设,toad查询中文会是qQ?/p>
TNS_ADMIN=C:\instantclient_11_2 Path=C:\instantclient_11_2 4、保存以下内容ؓ注册表文Ӟ导入注册表(路径部分Q请自己修改Q?/p>
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient10g_home] "NLS_LANG"="SIMPLIFIED CHINESE_CHINA.ZHS16GBK" "ORACLE_BUNDLE_NAME"="Enterprise" "ORACLE_GROUP_NAME"="Oracle - OraClient10g_home" "ORACLE_HOME"="C:\\instantclient_11_2" "ORACLE_HOME_KEY"="SOFTWARE\\ORACLE\\KEY_OraClient10g_home" "ORACLE_HOME_NAME"="OraClient10g_home" 5、徏立tnsnames.oraQƈ保存到安装目录:C:\instantclient_11_2 q个q里׃多说?/p>
# tnsnames.ora Network Configuration File: D:\oracle\product\10.2.0\client_1\network\admin\tnsnames.ora # Generated by Oracle configuration tools. ORCL = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = orcl) 6、测试: C:\Documents and Settings\Administrator>sqlplus /nolog SQL*Plus: Release 11.2.0.3.0 Production on 星期?4?28 10:10:10 2012 Copyright (c) 1982, 2010, Oracle. All rights reserved. SQL> conn scott/tiger@orcl 已连接?/p>
SQL> xQ安装已l完成。toad、PLSQL Developer{工P以及应用软g都可以正怋用了?/p>
昨天H然有客户反应系l无法正常的操作了!感到很震惊啊Q系l一直运行正常啊Q怎么会突然出问题。于是赶紧跟t调查终于发C问题的根源?/p>
问题一Q数据库 'XXXX' 的事务日志已满。若要查明无法重用日志中的空间的原因Q请参阅 sys.databases 中的 log_reuse_wait_desc ?/p>
问题二:无法为数据库 'XXX' 中的对象 ''PK_tbl_XXXX' 分配I间Q因?'PRIMARY' 文gl已满。请删除不需要的文g、删除文件组中的对象、将其他文gd到文件组或ؓ文gl中的现有文件启用自动增长,以便增加可用盘I间? 对于解决q两个问题的解决Ҏ如下Q在|上搜烦了一把,问题解决了。现在整理了如下Q: 问题一的解x法: Ҏ1Q?nbsp; MSSQL2005日志的收~?/strong> Ҏ2Q下面的所有库名都指你要处理的数据库的库名 c.附加数据? 特别注意Q?span style="color: #008080">--最好备份日志,以后可通过日志恢复数据。。?/span> 问题二的解决ҎQ?/strong> 解决ҎQ?br />1.查你的磁盘剩余空间是否?如果没有盘剩余I间,则清理磁?腑ևI间 2.查你的磁盘分区格?br />如果是FAT16,则数据文件最大只能是2G 3.查一下你有没有限制数据库文g的大?br />企业理?-右键你的数据?-属?-文g增长限制--如果有限制大?取消限制 4.查你的SQL版本,如果你用MSDE,则限制了数据文g最大是2G 5.你也可以?primary l添加新的数据文件来解决q个问题 或?选中数据?>属?>文gQ添加一个新文g
AND Professional_code NOT IN (SELECT professional_code FROM bm_report_status WHERE status <> 0 AND object_code=15074 AND time_code='MO201211')) t
where rolename=t.RN and member in(select member from bm_menberofobject where objectForUser=15074))
SELECT Professional_name, STUFF(( SELECT',' + member FROM TestTitle subTitle WHERE Professional_name = TestTitle.Professional_name
其实是有办法可以大大提升数据库运行效率的Q这要求我们的服务h员要学会数据库日常维护的高技巧,而且是必d会?br />
下面是数据库效率提升技巧的全面内容Q徏议所有服务h员自行练习ƈ用在实际工作中,要求熟练掌握?br />
技巧一Q重建烦?/strong>
效率提升指数Q高
特点Q一二三买单Q灰常的快,一下就弄完可以Ch了?br />
案例Q某市T1商N?百万行数据Q原速度五秒Q重建烦引后两秒不到Q速度提升q一倍。不要小看这几秒Q对市来讲Q那意味着不必要排镉K?br />
׃数据库日常写操作频繁Q烦引的工作效率会越来越低,速度自然大受影响Q很多客户会有这U感觉,前半q还非常快,后半q就受不了了。刚刚到q底Q正好是出报告、查资料的年养I偏偏软g慢得要命Q服务h员也别想有好日子q,陪着加班吧,q解决不了问题Q也让h家心理舒服点。这L日子可以q去了?br />
命o1QDBCC DBREINDEX (表名U?"",70) ---针对主要影响速度的表Q一般如rdrecords、salebillvouchs、pp_mrpdetails、pp_rmrpdetails
说明Q只对主要表操作Q媄响速度的当然是q几个大表,速度解决问题Q也不媄响客户?br />
命o2Qexec sp_msforeachtable "DBCC DBREINDEX(""?"")" ---数据库所有表重徏索引
说明Q不太徏议,除非太咸?br />
特别指出Q重建烦引前必须断网Q以保证所有客L无h在操作YӞ你懂?br />
技巧二Q表分区
效率提升指数Q超?br />
特点Q慢工出快活。硬盘越多,它就快Q所有硬盘一赯{当然快;CPU多Q它更快,sqlserver的引擎对q个有优化设计;设计得越合理Q它q常滴快,例如历史数据按年存放Q因Z一般不用嘛Q那数据库只对你要操作的部分分区索,自然飞快?br />q有Q必d是sql2005及以上版本,人家买的ERP你还装sql2000Q去d?br />
案例QNC、U8 10.0Q是的,它们用的是表分区,所以数据越P速度也越Hi
没有做表分区之前Q客h痛苦的,你也得痛苦,因ؓ你不明白几万元的服务器怎么q不{一个T6Q但NCq么却可以在宽带上溜溜的跑QU8 10.0q不分年度裤呢,׃个年度还用爬的?如果我说可以提升五倍甚x高的速度Q你信不信?反正我是信了?br />
真的?br />
q个有点炚wQ因求有更多的数据库知识Q不q初中生的水q也够用了,来吧?br />
1.为数据库Z文gl(可以建多个)Q最好是存放于不同磁盘上。这h率得以最大化Q想一惛_Q我们查一个年度所有收发记录,三个盘一赯{Q是不是原来速度的三倍?
ALTER DATABASE 数据库名 ADD FILEGROUP 文gl名
2.一个文件组可放|多个文Ӟ下面Q只Z个文件组分配一个文ӞcL吧?br />
ALTER DATABASE 数据库名 ADD FILE (NAME = N"文gl名", FILENAME = N"存放路径",SIZE = 5MB , FILEGROWTH = 10% ) TO FILEGROUP 文gl名
3.创徏分区函数。这个函数是本文件组专有的,再徏其它的文件组q得再搞一个。主要是讑֮Q包括预讄有的数据从哪里开始水q_Ԍ比如我们假设U8 10.0的上一q度最后一行rdrecords记录的Id?000000Q那么就可以讑֮q个|q以内的记录会切割保存到W一个分Z?br />
CREATE PARTITION FUNCTION [函数名] (int) AS RANGE LEFT FOR VALUES (5000000,8274249,12000000)
此句表示Q分三个区存攑֎先的数据
4.分区函数绑定到分区架构?
CREATE PARTITION SCHEME [架构名]
AS PARTITION [函数名]
TO ([PRIMARY],[文gl名],[PRIMARY],[文gl名],[PRIMARY],[文gl名])
5.删除表的主键Q必d除,表担心,主键可以再徏?
ALTER TABLE 数据表名U?DROP CONSTRAINT [主键]
6.删除聚集索引Q如果有的话Q我q没扑ֈ命oQ现在是手动删除?br />
7.开始做表分?
ALTER TABLE 数据表名U?add CONSTRAINT [主键] PRIMARY KEY CLUSTERED (主键字段?
ON [SHEME_rdrec](主键字段?
你看Q这不是恢复了主键吗
不过q是得手动恢复原来的聚集索引Q这个我再查查语句吧
特别提出Q?/strong>
数据库收~ƈ不能提高数据库的d效率Q正相反Q它反而更慢了。原因,是收~后数据库内部的数据存储发生位移Q也是索引变得更低效?br />q种情况下,必须再做一ơ烦引重建,但我发现g只要收羃了以后,数据库都慢,重徏索引也恢复不到原来的速度Q一下想不明白道理,而且做的试ơ数也有限?br />(转帖?http://bbs.iufida.com/thread-174625-1-1.html)数学函数
trunc(45.923Q?) 按指定精度截断十q制?l果Q?5.9
mod(1600,300) 求除法余?l果Q?00
abs(numeric_expr) ?a target="_blank">l对?/a>
ceiling(numeric_expr) 取大于等于指定值的最整?
avgQnumeric_exprQ取q_?
exp(float_expr) 取指?
floor(numeric_expr) 于{于指定值得最大整?
pi() 3.1415926.........
power(numeric_expr,power) q回powerơ方
rand([int_expr]) 随机C生器
round(numeric_expr,int_expr) 安int_expr规定的精度四舍五?
sign(int_expr) Ҏ正数,0,负数,,q回+1,0,-1
sqrt(float_expr) qx?
~辑本段日期、时间函?/span>
getdate() q回日期
datename(datepart,date_expr) q回名称?June
datepart(datepart,date_expr) 取日期一部䆾
datediff(datepart,date_expr1.dateexpr2) 日期?
dateadd(datepart,number,date_expr) q回日期加上 number
上述函数中datepart?
写法 取值和意义
yy 1753-9999 q䆾
qq 1-4 ?
mm 1-12 ?
dy 1-366 ?
dd 1-31 ?
wk 1-54 ?
dw 1-7 周几
hh 0-23 时
mi 0-59 分钟
ss 0-59 U?
ms 0-999 毫秒
日期转换
convert()
~辑本段pȝ、其他函?/span>
suser_name() 用户d?
user_name() 用户在数据库中的名字
user 用户在数据库中的名字
show_role() 对当前用戯v作用的规?
db_name() 数据库名
object_name(obj_id) 数据库对象名
col_name(obj_id,col_id) 列名
col_length(objname,colname) 列长?
valid_name(char_expr) 是否是有?a target="_blank">标识W?/a>
Q?/span>.右键在清除日志的数据库,?#8220;TestDB”Q点?/span>[新徏查询QQQ?/span>]
Q?/span>.输入以下SQL语句Q其?#8220;TestDB”是数据库名称
DUMP TRANSACTION TestDB WITH NO_LOGQ?执行该SQLQ成功后l箋以下操作
Q?/span>.右键该数据库节点Q点?/span>[dQTQ?/span>] -> [收羃QSQ?/span>] -> [文gQFQ?/span>]
Q?/span>.在弹出的“收羃文g”对话框中Q将“文gcdQTQ?#8221;选ؓ“日志”Q将“收羃操作”选中“在释放未使用的空间前重新l织(OQ?#8221;
Q?/span>.?#8220;文件收~到QKQ?#8221;文本框中输入后面提示的最大的数|点击[定]卛_?/span>
1.清空日志
DUMP TRANSACTION 库名 WITH NO_LOG
2.截断事务日志Q?br />BACKUP LOG 库名 WITH NO_LOG
3.收羃数据库文?如果不压~?数据库的文g不会减小
企业理?/span>--右键你要压羃的数据库--所有Q?-收羃数据?-收羃文g
--选择日志文g--在收~方式里选择收羃至XXM,q里会给Z个允许收~到的最M?直接输入q个?定可以了
--选择数据文g--在收~方式里选择收羃至XXM,q里会给Z个允许收~到的最M?直接输入q个?定可以了
也可以用SQL语句来完?
--收羃数据?/span>
DBCC SHRINKDATABASE(库名)
--收羃指定数据文g,1是文件号,可以通过q个语句查询?select * from sysfiles
DBCC SHRINKFILE(1)
4.Z最大化的羃日志文?如果是sql 7.0,q步只能在查询分析器中进?
a.分离数据?
企业理?/span>--服务?-数据?-右键--分离数据?/span>
b.在我的电脑中删除LOG文g
企业理?/span>--服务?-数据?-右键--附加数据?/span>
此法生成新的LOGQ大只?00多K
或用代码Q?
下面的示例分?pubsQ然后将 pubs 中的一个文仉加到当前服务器?br />a.分离
EXEC sp_detach_db @dbname = '库名'
b.删除日志文g
c.再附?br />EXEC sp_attach_single_file_db @dbname = '库名',
@physname = 'c:/Program Files/Microsoft SQL Server/MSSQL/Data/库名.mdf'
5.Z以后能自动收~?做如下设|?
企业理?/span>--服务?-右键数据?-属?-选项--选择"自动收羃"
--SQL语句讄方式:
EXEC sp_dboption '库名', 'autoshrink', 'TRUE'
6.如果想以后不让它日志增长得太?br />企业理?/span>--服务?-右键数据?-属?-事务日志
--文件增镉K制ؓxM(x是你允许的最大数据文件大?
--SQL语句的设|方?
alter database 库名 modify file(name=逻辑文g?maxsize=20)
以下为日志处理方?br />一般不做第4,6两步
W?步不安全,有可能损坏数据库或丢失数?br />W?步如果日志达C?则以后的数据库处理会p|,在清理日志后才能恢复.
如果是FAT32,则数据文件最大只能是4G
改ؓNTFS分区则没有这U限?/span>
alter database 库名 add file(NAME = 逻辑文g?FILENAME = 'c:/实际文g?ndf'
DBCC SHRINKDATABASE(upd364)
地址 http://blog.csdn.net/dmlk31/archive/2008/01/02/2010216.aspx
本文攉了网上关于Left join , Right Join, Inner Join 的相兛_容,非常实用Q对于理解原理和具体应用都很有帮助!
一.先看一些最单的例子
例子
Table A
aid adate
1 a1
2 a2
3 a3
TableB
bid bdate
1 b1
2 b2
4 b4
两个表a,b相连?要取出id相同的字D?
select * from a inner join b on a.aid = b.bidq是仅取出匹配的数据.
此时的取出的?
1 a1 b1
2 a2 b2
那么left join ?
select * from a left join b on a.aid = b.bid
首先取出a表中所有数?然后再加上与a,b匚w的的数据
此时的取出的?
1 a1 b1
2 a2 b2
3 a3 I字W?
同样的也?strong>right join
指的是首先取出b表中所有数?然后再加上与a,b匚w的的数据
此时的取出的?
1 a1 b1
2 a2 b2
4 I字W?b4
LEFT JOIN ?LEFT OUTER JOIN?
左向外联接的l果集包?LEFT OUTER 子句中指定的左表的所有行Q而不仅仅是联接列所匚w的行。如果左表的某行在右表中没有匚w行,则在相关联的l果集行中右表的所有选择列表列均为空?/p>
? left join/right join/inner join操作演示
Q-Q-Q-Q-Q-Q-Q-Q-QE以下为网上的一点资料]Q-Q-Q-Q-Q-Q-Q-Q-Q-
LEFT JOIN操作用于在Q何的 FROM 子句中,l合来源表的记录。?LEFT JOIN q算来创Z个左边外部联接。左边外部联接将包含了从W一个(左边Q开始的两个表中的全部记录,即在第二个Q右边)表中q没有相W值的记录?
语法Q?/span>
FROM table1 LEFT JOIN table2 ON table1.field1 compopr table2.field2
说明Q?/span>
① table1, table2参数用于指定要将记录l合的表的名U?br />
② field1, field2参数指定被联接的字段的名U。且q些字段必须有相同的数据cd及包含相同类型的数据Q但它们不需要有相同的名U?br />
③ compopr参数指定关系比较q算W:"="Q?"<"Q?">"Q?"<="Q?">=" ?"<>"?br />
④ 如果在INNER JOIN操作中要联接包含Memo 数据cd?OLE Object 数据cd数据的字D,会发生错误?/span>
?相关的复杂的解释和实?/font>
? 外部q接和自联接 inner join({D? 只返回两个表中联l字D늛{的?left join(左联? q回包括左表中的所有记录和双中联l字D늛{的记录 right join(双? q回包括双中的所有记录和左表中联l字D늛{的记录 on 指定表间联结字段及其关系的等?"=" 表达? q回 true ?false. 当表辑ּq回 true ? 则查询中包含该记? ! 外部q接只能操作已存在于数据库中的数?br />
update (ctarticle as a left join ctclass as c on a.classid = c.classid) left join cttag as b on a.articleid = b.articleid
set tag=tag+' ', b.articleid=a.articleid, b.classid=a.classid, b.nclassid=a.nclassid
where a.classid=23 and a.nclassid=0 and tagid is not null
update (ctarticle as a left join (ctnclass as c left join ctclass as d on c.classid = d.classid) on a.nclassid = c.nclassid and a.classid = c.classid) left join cttag as b on a.articleid = b.articleid set tag=d.class+' '+c.nclass, b.articleid=a.articleid, b.classid=a.classid, b.nclassid=a.nclassid where a.classid=23 and a.nclassid=197;
更新操作
左连接中数据的筛?
insert into cttag(articleid,classid,nclassid) select a.articleid,a.classid,a.nclassid from ctarticle a left join cttag b on a.articleid=b.articleid where b.articleid is null
//本语句功能ؓ, 昄主表的全部内? 插入数据到副表中没有的数?
//主要作用? 让数据减冗?
上例中的延箋
select a.*, b.*, c.*, d.* from cttag as d left join ((ctarticle as a left join ctclass as b on a.classid=b.classid) left join ctnclass as c on a.nclassid=c.nclassid) on d.articleid=a.articleid;
昄文章表中的全? 调用cd表中的栏?
select a.*, b.*, c.* from (ctarticle a left join ctclass b on a.classid=b.classid) left join ctnclass c on a.nclassid=c.nclassid
//作用, 有时在文章表中包含了在个别类别表中没有的数据, 用这个语法可以读出文章表的全部数?
//a ?文章? b Zcd, c 为子cd
同上? 选择q加数据时加上空?
insert into cttag(articleid,classid,nclassid,tag) select a.articleid,a.classid,a.nclassid,d.class+' '+c.nclass
from (ctarticle as a left join (ctnclass c left join ctclass d on c.classid=d.classid) on a.classid=c.classid and a.nclassid=c.nclassid) left join cttag as b on a.articleid = b.articleid where a.classid=4 and a.nclassid=154;
q接n个表, q追加数据到其中一个表, n=4
insert into cttag(articleid,classid,nclassid,tag) select a.articleid,a.classid,a.nclassid,d.class+c.nclass
from (ctarticle as a left join (ctnclass c left join ctclass d on c.classid=d.classid) on a.classid=c.classid and a.nclassid=c.nclassid) left join cttag as b on a.articleid = b.articleid where a.classid=1 and a.nclassid=1;
//解读
插入??(?,?,?,?)
选择 别名a.?, 别名a.?, 别名a.?, 别名d.? 加上 别名c.?
?(? 别名a 左连?(? 别名c 左连?? 别名d ?别名c.? {于 别名d.?) ?别名a.? {于 别名c.? ?别名a.?=别名c.?) 左连?? 别名b ?别名a.? {于 别名b.? 在那?别名a.?=1 ?别名a.?=1
q接两个? q追加数据到其中一个表
insert into cttag(articleid,classid,nclassid)
select a.articleid,a.classid,a.nclassid
from ctarticle as a left join cttag as b on a.articleid = b.articleid where a.classid=1 and a.nclassid=1;
//解读
插入??(?,?,?)
选择 别名a.?, 别名a.?, 别名a.?
?? 别名a 左连?? 别名b ?别名a.? {于 别名b.? 在那?别名a.?=1 ?别名a.?=1
左连?
同步两表的数?
update ctarticle a inner join cttag b on a.articleid = b.articleid set b.classid=a.classid, b.nclassid=a.nclassid;
//解读
更新 ? 别名a 联接 ? 别名2 ?别名a.? {于 别名b.? 讄 别名b.? 更新?别名a.?, 别名b.? 更新?别名a.?
叛_q接
select a.*, b.* from bunclass a right join ctclass b on a.classid=b.classid where a.nclassid=20
查询别名 a,b ? 只匹?b 表中的内?
d数据到连接表之一
insert into cttag ( tag, articleid ) select top 1 b.tag, a.articleid from ctarticle as a left join cttag as b on a.articleid = b.articleid where a.articleid order by a.articleid desc;
变通中的用法二
insert into bureply
select b.*, a.classid, a.nclassid
from article as a inner join reply as b on a.articleid = b.articleid
where classid=50;
实际应用中的变?
insert into butag ( tag, articleid, classid, nclassid)
select b.tag, a.articleid, a.classid, a.nclassid
from article as a inner join tag as b on a.articleid = b.articleid
where classid=24;
d数据到其他表
insert into butag ( tag, articleid )
select b.tag, a.articleid
from article as a inner join tag as b on a.articleid = b.articleid
where a.articleid<>false;
//解读
d?接收??,?)
选择 别名b.?, 别名a.?
?? 表名a 联接 ? 表名b ?别名a.列c {于 别名b.列c
在哪?别名a.列c 不等?没有
实际应用中的变?
select b.tag, a.articleid, a.classid, a.nclassid
from article as a inner join tag as b on a.articleid = b.articleid
where a.classid=24;
查询
select b.tag, a.articleid
from article as a inner join tag as b on a.articleid = b.articleid
where a.articleid<>false;
//解读
选择 别名b.? 别名a.?
?? 别名a 联接 ? 别名b ?别名a.列c = 别名b.列c
在哪?别名a.列c 不等?没有
? as 不是必要
FOR temp2 IN EXECUTE'SELECT CAST(x5.no AS varchar), tbl_headmaterial.material_name,tbl_headmaterial.material_unit,
CAST(round(COALESCE(CAST(x1.count AS numeric),0),3) AS varchar) ,
CAST(round(COALESCE(CAST(x2.count AS numeric),0),3) AS varchar) ,
CAST(round(COALESCE(CAST(x3.count AS numeric),0),3) AS varchar) ,
CAST(round(COALESCE(CAST(x4.count AS numeric),0),3) AS varchar) ,
CAST(round(COALESCE(CAST(x1.count AS numeric),0)+COALESCE(CAST(x2.count AS numeric),0)-COALESCE(CAST(x3.count AS numeric),0)-COALESCE(CAST(x4.count AS numeric),0),3) AS varchar) FROM
(SELECT DISTINCT no AS no FROM (SELECT CAST(no as int4) as no FROM x1 UNION SELECT CAST(no as int4) AS no FROM x2 UNION SELECT CAST(no as int4) as no FROM x3 UNION SELECT CAST(no as int4) as no FROM x4)AS x6) AS x5
LEFT JOIN x1 ON x5.no = x1.no LEFT JOIN x2 ON x5.no = x2.no LEFT JOIN x3 ON x5.no = x3.no LEFT JOIN x4 on x5.no = x4.no LEFT JOIN tbl_headmaterial on x5.no = tbl_headmaterial.material_no'
LOOP
RETURN NEXT temp2;
END LOOP;
EXECUTE 'DROP table x1';
EXECUTE 'DROP table x2';
EXECUTE 'DROP table x3';
EXECUTE 'DROP table x4';
RETURN;
END;
$$
language plpgsql;
select * from fun1('2007-12-30') store (no varchar,name varchar,unit varchar ,x1 varchar,x2 varchar,x3 varchar,x4 varchar,x5 varchar);
表A2
id B
2 22
3 33
5 55
表A3
id C
1 111
2 222
7 777
表A4
id D
5 5555
6 6666
7 7777
现在要写个查询,l果为,怎么写呢
id A B C D
1 1 0 111 0
2 2 22 222 0
3 3 33 0 0
5 0 55 0 5555
6 0 0 0 6666
7 0 0 777 7777
select a5.id,COALESCE(a1."A",0) as A,COALESCE(a2."B",0) as b,
COALESCE(a3."C",0) as c,COALESCE(a4."D",0) as d from
(select distinct id as id from (select id from a1 union
select id from a2 union select id from a3
union select id from a4)as a6) as a5 left join a1 on a5.id = a1.id left join a2 on a5.id = a2.id left join a3 on a5.id = a3.id
left join a4 on a5.id = a4.id
例子一
CREATE OR REPLACE FUNCTION instr(character varying, integer)
RETURNS integer AS
$BODY$
declare
str alias for $1;
ind alias for $2;
begin
return ind+100;
end;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
> select instr('aaa',100) ;
> 200
例子?/font>
如果一?PL/pgSQL 函数的返回类型声明ؓ一个多态类?Q?tt class=TYPE> 或?Q,那么׃创徏一个特D的参数Q?。它的数据类型是函数的实际返回类型,和从实际输入cd推导推导cd一?Q参?Section 31.2.5Q?q样允许函数访问它的实际返回类型,?Section 35.4.2 里显C的那样? 初始化ؓI,q且可以被函C改,所以,如果需要,它可以用于保存返回| 虽然qƈ非必ȝ?tt class=LITERAL> q可以给予一个别名。比如,q个函数可以在Q何有 操作W的数据cd上运转:
create or replace function addT (v1 anyelement, v2 anyelement, v3 anyelement)
returns anyelement as $$
declare
res alias for $0;
begin
res := v1+v2+v3;
return res;
end;
$$language plpgsql;
> select addT(100,200,300)
> 600
例子?/font>
variable%TYPE
提供一个变量或者表字段的数据类型?你可以用q个声明要保存数据库数值的变量。比如,假如你在 表里面有一个字D叫 。要声明一个和 cd相同的变量,你可以写Q?
user_id users.user_id%TYPE;
通过使用 Q你必须知道你引用的l构的数据类型, q且Q最重要的是Q如果被引用的数据cd在将来变化了Q比如:你把 的类型从 Ҏ Q,你也不需要修改你的函数定义?
对多态的函数特别有用Q因为内部变量的数据cd可能在不同调用中是不一L?我们可以通过l函数的参数或者结果占位符附加 的方法来创徏合适的变量?/p>
例子?/font>
行类?br>name table_name%ROWTYPE;
name composite_type_name;
一个复合类型变量叫?em class=FIRSTTERM>?/em>变量Q或?em class=FIRSTTERM>row-type变量Q?q样的一个变量可以保存一?tt class=COMMAND>或?命ol果的完整一行,只要命o的字D集匚w该变量声明的cd?行数值的独立的字D|使用常用的点表示法访问的Q比??
一个行变量可以声明为和一个现有的表或者视囄行类型相同,Ҏ是?table_name%ROWTYPE 表示法; 或者你也可以声明它的类型是一个复合类型的名字。(因ؓ每个表都有一个相兌的同名数据类型, ?PostgreSQL 里实在是无所谓你写不?。但是有 的Ş式移植性更好。)
函数的参数可以是复合cdQ表的完整行Q。这个时候, 对应的标识符 $n 是一个行变量Qƈ且可以从中选取字段Q比??
在一个行cd的变量中Q只可以讉K用户定义的表中行的属性, 不包?OID 或者其他系l属性(因ؓ该行可能来自一个视图)?该行cd的数据域l承表中?n) q种cd字段的尺寸和_ֺ?
q里是一个用复合类型的例子Q?br>CREATE TABLE tbl_store1
(
store_no integer NOT NULL DEFAULT nextval('tbl_store1_sq'::regclass),
parent_id integer,
"type" integer,
"values" real,
CONSTRAINT tbl_store1_pkey PRIMARY KEY (store_no)
)
插入?1 1 1 1;
CREATE OR REPLACE FUNCTION merge(t_row tbl_store1)
RETURNS text AS
$BODY$
declare
t2_row tbl_store1%rowtype;
begin
select * into t2_row from tbl_store1 ;
return t_row.values || t2_row.values;
end;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
> select merge(t.*) from tbl_store1 t ;
> 11
例子?/font>
/**
create or replace function logfun1(log text) returns timestamp as $$
begin
insert into tbl_store1 values(3,1,1,1,'now');
return 'now';
end;
$$ language plpgsql;
select logfun1('test');
**/
create or replace function logfun2(log text) returns timestamp as $$
declare
ctime timestamp;
begin
ctime :='now';
insert into tbl_store1 values(6,2,1,1,ctime);
return ctime;
end;
$$ language plpgsql;
select logfun2('aaa');
? 的实例里Q?PostgreSQL 的主分析器在? 准备执行计划的时候知道字? 应该解释? cdQ因? 的目标字D就是该cd。所以,它会在这个时候从q个字串中计一个常量, 然后在该服务器的整个生存期中的所? 调用中用这个常量。不消说Q这可不是程序员惌的?
?tt class=FUNCTION>里, PostgreSQL 的主分析器ƈ不知? 应该转换成什么类型, 因此它返回一个包含字W串 的类型ؓ 的数据倹{?在随后给局部变?tt class=VARNAME>赋值时Q?PL/pgSQL解释器通过调用 ?tt class=FUNCTION> 把这个字W串转换? cd的变量?因此Q计出的时戛_会按照程序员希望的那样在每次执行的时候都更新?
记录变量的易变性天性在q种l合上提Z一个问题?在一个记录变量在语句或者表辑ּ中用时Q?该字D늚数据cd在同一个表辑ּ的不同调用期间不能修改, 因ؓ该表辑ּ准备使用的是q行W一ơ到达该表达式时出现的数据类型?在写处理过一个表的事件的触发器过E的时候一定要把这个记住。(必要时可以用l开q个问题。)
例子?/font>
create or replace function tSInto () returns varchar as
$$
declare rec record;
begin
select into rec * from tbl_store1 where values =1;
if not found then
return 'test';
else
return 'tttt';
end if;
end;
$$
language plpgsql;
select tSInto();
create or replace function tSInto () returns varchar as
$$
declare rec record;
begin
select into rec * from tbl_store1 where values =1;
if rec.values isNULL then
return 'okkkkkkk';
else return 'test';
end if ;
end;
$$
language plpgsql;
select tSInto();
例子?br>create or replace function cur1 () returns text as
$$
declare
curs1 CURSOR for select * from tbl_store1;
res text :='';
a varchar;
b varchar;
c varchar;
d varchar;
e varchar;
begin
OPEN curs1;
loop
fetch curs1 into a,b,c,d,e;
if not found then
return 'error';
exit;
end if;
res = 'test'||res;
end loop;
close curs1;
return res;
end;
$$
language plpgsql;
CREATE OR REPLACE FUNCTION cur1()
RETURNS text AS
$BODY$
declare
curs1 CURSOR for select * from tbl_store1;
res text :='';
a varchar;
b varchar;
c varchar;
d varchar;
e varchar;
begin
OPEN curs1;
loop
fetch curs1 into a,b,c,d,e;
if (found) then
if (a is null) then
a = '';
end if ;
if (b is null) then
b = '';
end if ;
if (c is null) then
c = '';
end if ;
if (d is null) then
d = '';
end if ;
if (e is null) then
e = '';
end if ;
res = res || a || b || c || d || e;
else
exit;
end if;
end loop;
close curs1;
return res;
end;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
select cur1();