2009年6月21日
oracle debug
2009年6月3日
本人证实可用的twitter连接方法
2 gmail+Twitter Gadget
可能需要在英文实验室下启用 "Add any gadget by URL" 功能
添加这个URL作为 gadget: https://twittergadget.appspot.com/gadget-gmail.xml
完成后要通知twitter允许此插件,需要走代理,地址在twitter gadget中有。
在twitter的页面中allow.
更多见:https://groups.google.com/group/twitter_in_chinese/web/twitter?hl=zh-CN
2009年5月31日
利用GOOGLE系列工具建立安全无障碍的(群)博客
而https是加密传输的,路由器不知道传输的具体内容,象银行支付等就是基于此协议的。
更多介绍见:http://zh.wikipedia.org/w/index.php?title=Https&variant=zh-cn
主要思路:
1、用gmail或google docs加密撰写稿件,投递到blogspot站点。
2、用google reader加密订阅blogspot博客。
好处:
1、无需自己架设主机。
2、全程安全、无任何障碍。
缺点:
网友在传播时,复制粘贴到别的网站时可能会受到限制。
详细步骤:
1、申请gmail:
https://www.gmail.com
2、申请blogger帐号(也是google产品):
用代理如https://www.sneakme.net(这个代理非常快,可流畅播放youtube)上www.blogger.com,用gmail帐号登录。
3、设置 blogger:
在“出版业”中可设置博客的独立域名,如我的www.tallrain.cn=tallrain.blogspot.com
对于独立域名,需将此域名解析转向到ghs.google.com或其它最终定义到有限IP的地址,如我的www.tallrain.cn解析转向到ghs.keso.cn。
在“供稿”页中可设置输出的feed地址,如http://feedproxy.google.com/tallrain,可在google的feed中加入广告。
在“电子邮件和移动博客”页中,可设置电子邮件发布地址,从你的GMAIL中将内容直接发送到此地址即可实现发布博客。其它人向此地址发送邮件也可以实现联合供稿,但建议用https://gmail.com,因为它是加密的。
4、用gmail写稿
这是最方便的,但是有个前提,不支持图片。
进入https://gmail.com,写邮件主题和正文,然后直接发送到第3步所定义的邮件地址即可。
带图片的情况后面单独讲。
5、用google docs写稿
如果是个人博客,其实写稿也非常容易。
在https://docs.google.com中新建文档,和WORD一样编辑、保存,然后点击右上角的 共享》以网页形式发布...》张贴到博客,定义好博客设置,如:
定义好之后就可以直接就文档发布到博客上了。和gmail一样,这过程全部是在google的服务器之间加密进行的,安全可靠,GFW无计可施。
google docs有一个好处就是支持图片,而且图片地址也是加密的,每次查看图片时都会向google的服务器发送一次查询的请求,图片的显示地址与文件名无关。
因此可以很放心方便地利用google docs实现多图的博客供稿,就象用word编辑文件一样方便。
google docs投递的稿件还可以通过原地址更新,只要重要发布一次就可以了。
6、利用gmail和google docs实现带图片的联合供稿
方法是首先在google docs里编辑稿件,然后点击右上角的 共享》以网页形式发布,发布在线文档,这样就生成了一篇在线文档,将文档地址的头从http://改为https://,这样图片的地址是经过google docs加密的网络地址。
然后就此发布后的文档全选》复制,在gmail中新建邮件,粘贴,就实现了在gmail中贴网络图片的目的。
7、博客订阅
https://www.google.com/reader,同样是加密的。
经由以上环节,所有数据传输都是在google的服务器间加密传输的。
8、其实建立博客群还有一个很简单的办法,就是首先在google reader中建立一个文件夹,用此文件夹订阅若干个博客RSS,然后将此文件夹共享,即可得到一个新的公用地址,然后得到一个对应的订阅RSS,如这个地址就是一组订阅http://www.google.com/reader/shared/user/17431774544185162274/label/%E6%9C%80%E8%BF%91%E6%B4%BB%E5%8A%A8,其RSS就是http://www.google.com/reader/public/atom/user%2F17431774544185162274%2Flabel%2F%E6%9C%80%E8%BF%91%E6%B4%BB%E5%8A%A8
2009年5月24日
Oracle迭代和存储过程练习2
create table SNLINK_DIM
(
ROOTID NUMBER(10),
SN VARCHAR2(10),
CID NUMBER(10),
LEVELID NUMBER(2),
DIM VARCHAR2(255)
)
;
二、创建ADDSNLINK触发器
CREATE OR REPLACE TRIGGER tg_addsnlink
AFTER INSERT ON snlink
FOR EACH ROW
DECLARE
pragma AUTONOMOUS_TRANSACTION;
rootid NUMBER;
cid NUMBER;
fsn VARCHAR2(100);
flevid NUMBER;
fdim VARCHAR2(100);
clevid NUMBER;
cdim VARCHAR2(100);
cursql VARCHAR2(1000);
mdim VARCHAR2(100);
mdim2 VARCHAR2(100);
i NUMBER;
TYPE myrecord IS RECORD(levelid NUMBER, dim VARCHAR2(100));
myrec myrecord;
CURSOR myfid(thesn VARCHAR2) IS SELECT levelid, dim FROM snlink_dim WHERE sn=thesn;
CURSOR myfid2(rid NUMBER, lev NUMBER, fdim VARCHAR2, flen NUMBER)
IS SELECT MAX(DIM) FROM snlink_dim
WHERE rootid = rid
AND levelid = lev
AND SUBSTR(dim, 1, flen+1) = fdim || ',';
BEGIN
cid := :new.id;
rootid := getrootid(:new.fid);
IF :new.fid<0 THEN -- add new root
rootid := :new.id;
clevid := 1;
cdim :='1';
cursql := 'INSERT INTO snlink_dim VALUES(' || rootid || ',''' || :new.sn || ''',' || rootid;
cursql := cursql || ',' || 1 || ',''1'')';
EXECUTE immediate cursql;
COMMIT;
ELSE -- to get levelid and dim
cid := :new.id;
fsn := getsnbyid(:new.fid);
OPEN myfid(fsn);
FETCH myfid INTO myrec;
flevid := myrec.levelid;
fdim := myrec.dim;
clevid := flevid + 1; -- get levelid
OPEN myfid2(rootid, clevid, fdim, length(fdim));
FETCH myfid2 INTO mdim;
IF (mdim is null) or (mdim = '') THEN -- first child
cdim := fdim || ',1';
ELSE --
i := 1;
WHILE i>0 LOOP
i := INSTR(mdim,',');
if i>0 THEN
mdim := SUBSTR(mdim,i+1,length(mdim)-i);
END IF;
END LOOP;
mdim2 := TO_CHAR(TO_NUMBER(mdim)+1);
cdim := fdim || ',' || mdim2;
END IF;
cursql := 'INSERT INTO snlink_dim VALUES(' || rootid || ',''' || :new.sn || ''',' || cid;
cursql := cursql || ',' || clevid || ',''' || cdim || ''')';
EXECUTE immediate cursql;
COMMIT;
END IF;
END;
三、建SNINFO表
CREATE TABLE sninfos
(
sn varchar2(10),
pn varchar2(10)
);
四、定义产品结构
+pn1
-pn2
+pn3
+pn4
-pn5
五、创建批量导入的存储过程
CREATE OR REPLACE PROCEDURE batch_add_snlink(beginid NUMBER, qty NUMBER)
AS
i NUMBER;
cursql VARCHAR2(1000);
sn1 VARCHAR2(10);
sn2 VARCHAR2(10);
sn3 VARCHAR2(10);
sn4 VARCHAR2(10);
sn5 VARCHAR2(10);
BEGIN
i := beginid;
WHILE i< (beginid + qty) LOOP
sn1 := 'sn1-' || i;
sn2 := 'sn2-' || i;
sn3 := 'sn3-' || i;
sn4 := 'sn4-' || i;
sn5 := 'sn5-' || i;
cursql := 'INSERT INTO sninfos values('''||sn1||''', ''pn1'')';
EXECUTE immediate cursql;
COMMIT;
cursql := 'INSERT INTO sninfos values('''||sn2||''', ''pn2'')';
EXECUTE immediate cursql;
COMMIT;
cursql := 'INSERT INTO sninfos values('''||sn3||''', ''pn3'')';
EXECUTE immediate cursql;
COMMIT;
cursql := 'INSERT INTO sninfos values('''||sn4||''', ''pn4'')';
EXECUTE immediate cursql;
COMMIT;
cursql := 'INSERT INTO sninfos values('''||sn5||''', ''pn5'')';
EXECUTE immediate cursql;
COMMIT;
addsnlink(sn1, sn2);
addsnlink(sn1, sn3);
addsnlink(sn3, sn4);
addsnlink(sn4, sn5);
i := i + 1;
END LOOP;
END;
六、调用batch_add_snlink(1001,1000)插入100条记录,并查看sninfos, snlink, snlink_dim的数据情况。
七、从snlink表查询数据生成交叉表
SELECT
i1.sn as pn1,
i2.sn as pn2,
i3.sn as pn3,
i4.sn as pn4,
i5.sn as pn5
FROM
sninfos i1,
sninfos i2,
sninfos i3,
sninfos i4,
sninfos i5,
snlink s1,
snlink s2,
snlink s3,
snlink s4,
snlink s5
WHERE i1.sn = s1.sn
AND i2.sn = s2.sn
AND i3.sn = s3.sn
AND i4.sn = s4.sn
AND i5.sn = s5.sn
AND s1.id = s2.fid
AND i2.pn = 'pn2'
AND s1.id = s3.fid
AND i3.pn = 'pn3'
AND s3.id = s4.fid
AND s4.id = s5.fid
ORDER BY i1.sn
1120 rows selected in 0.889 seconds.
10000 rows selected in 6.707 seconds.
24092 rows selected in 25.335 seconds.
八、从snlink_dim表查询数据生成交叉表
SELECT
s1.sn as pn1,
s2.sn as pn2,
s3.sn as pn3,
s4.sn as pn4,
s5.sn as pn5
FROM
snlink_dim s1,
snlink_dim s2,
snlink_dim s3,
snlink_dim s4,
snlink_dim s5
WHERE s1.dim = '1'
AND s2.dim = '1,1'
AND s3.dim = '1,2'
AND s4.dim = '1,2,1'
AND s5.dim = '1,2,1,1'
AND s1.rootid = s2.rootid
AND s1.rootid = s3.rootid
AND s1.rootid = s4.rootid
AND s1.rootid = s5.rootid
ORDER BY s1.sn
1130 rows selected in 0.546 seconds.
10000 rows selected in 4.93 seconds.
24092 rows selected in 11.654 seconds.
九、创建BOM表1
CREATE TABLE bom1
(
pn VARCHAR2(10),
cpn VARCHAR2(10),
qty NUMBER(3)
);
输入以下数据:
+pn1
+pn2,1
-pn3,2
-pn6,2
+pn4,2
-pn5,1
-pn3,1
十、创建pn表
CREATE TABLE pn
(
pn VARCHAR2(10),
des VARCHAR2(1024)
);
十一、关联迭代查询
SELECT LEVEL, bom1.pn, bom1.cpn, pn.des, bom1.qty
FROM bom1, pn
WHERE bom1.cpn=pn.pn
START WITH bom1.pn='pn1'
CONNECT BY PRIOR cpn=bom1.pn
2009年5月12日
数据库多维迭代算法
关键词:数据库 迭代 递归 多维
一、两种传统的数据库迭代结构算法
对于数据库的迭代结构,有两种传统的算法:递归算法和边界算法。
比如对于下面图1的结构:
图1
递归算法的数据结构如表1所示:
| 节点id | 节点值 | 父节点id |
| 1 | 1111 | -2 |
| 3 | 1112 | 1 |
| 4 | 1113 | 1 |
| 5 | 1114 | 4 |
| 6 | 1115 | 4 |
| 7 | 1116 | 1 |
| 8 | 1117 | 7 |
| 9 | 1118 | 8 |
表1
父节点id如为负值,表示这是一个根节点。
从表1可以看出,我们用若干组父-子递归的结构来表达完整的迭代结构。
这种算法很容易理解,但是缺点也很明显:
要从任意一个节点展现整个结构时,要从此节点向根节点做一个逆向递归,然后由根节点向所有层的子节点做N次正向递归,数据库的运算开销很大。特别是正向递归到达所有外围节点时要做一个空查询,形成浪费。
尽管oracle对递归查询有优化算法,如
select distinct *
from table1
start with 节点值='1111'
connect by prior 节点id=父节点id
这样可以形成以'1111'为根的整个节点树结构。
但是这种优化在统计时是无能为力的,而且此查询返回的结果丢失了很多结构的细节。
下面我们再来分析第二种迭代算法:边界算法。
这种算法有点类似邮递员送信路径的传统数学难题,方法是将节点的边界串起来,同时记录其结构。
对于图1的结构,数据库中记录如表2所示:
| 节点值 | 结构id | 节点顺序 | 节点层次 |
| 1111 | 1001 | 1 | 1 |
| 1112 | 1001 | 2 | 2 |
| 1113 | 1001 | 3 | 2 |
| 1114 | 1001 | 4 | 3 |
| 1115 | 1001 | 5 | 3 |
| 1116 | 1001 | 6 | 2 |
| 1117 | 1001 | 7 | 3 |
| 1118 | 1001 | 8 | 4 |
表2
这里1001是此结构的id。因此我们可以用结构id,仅通过一次查询,就可以将整个结构展现出来。
此算法的缺点是:
取子结构麻烦,比如我们要查询1113-1114-1115的子结构,我们要从1113开始将整个结构截取出来,然后分析哪些是它的子结构。
数据更新麻烦,在插入或删除某个子结构时,要将节点顺序重新排序。
二、多维迭代算法的原理
所谓多维迭代算法,是指任意一个节点,在继承父节点的特性同时,创建自己的特性维度。
对于图1的结构,其数据库中的记录如表3所示:
| 节点值 | 结构id | 节点维度 |
| 1111 | 1001 | 1 |
| 1112 | 1001 | 1,1 |
| 1113 | 1001 | 1,2 |
| 1114 | 1001 | 1,2,1 |
| 1115 | 1001 | 1,2,2 |
| 1116 | 1001 | 1,3 |
| 1117 | 1001 | 1,3,1 |
| 1118 | 1001 | 1,3,1,1 |
表3
我们可以看出,任意一个节点都有其结构中的唯一维度,而且往左减一个维度就是其父节点的维度。因此我们要取子结构也非常方便,只要对节点维度从左开始截取若干位进行匹配就可以了。这种结构无需递归,因此统计时效率得到级数级的提升。
下面介绍多维迭代的一些扩展算法:
查询子结构
如查询1113的子结构,算法是取结构id=1001,且节点2维维度='1,2',返回1113、1114、1115共3条数据,且1114和1115是1113的子节点。
插入子结构
如我们要将图2的子结构插入1116这个节点上,即2221为1116的子节点:
图2
则运算方法为:首先获得2221的新维度(1,3,2),然后将整个子结构的第1维度更新为(1,3,2),最后最新子结构的结构id(1001)。
取消子结构
假如我们要取消1116-1117-1118这个子结构,那么首先获得新的结构id,然后用1替换子结构的前2维(1,3)。
替换子结构
假如我们用图2的子结构替换图1中1116-1117-1118的子结构,或者说用2221替换1116,则首先临时记录1116的结构id(1001)和维度(1,3),然后取消1116子结构,然后更新2221子结构的id和维度。
三、多维迭代算法的典型应用
ERP缺料统计
我们知道ERP的BOM是一个典型的递归结构,在进行缺料统计时,要把最顶层的料号展开成所有底层料号的集合,因此有很多的递归。
如果我们在表3的多维结构上增加数量属性,就可以得到一个类似BOM的结构体。即使我们不改动BOM,也可以通过第三方开发,把BOM结构映射为一个多维结构范式,从而减少递归运算。
包装装配数据统计
生产上的包装和装配数据通常采用递归结构,如果要对多组数据进行统计的话,要进行成千上万次的递归,效率极低。
如果包装和装配数据都采用多维结构存储的话,只要一次查询就可以导出统计报表了,而且报表数据还保留了完整的结构。
数据仓库应用
如果要对递归数据进行数据仓库处理的话,只要将递归结构映射为一个多维结构,就可以方便地储存和统计递归数据,同时保留其结构。
家谱
我们只要在多维结构上分别定义父亲维度和母亲维度,就可以方便地进行多数家谱运算。