November | ||||||
---|---|---|---|---|---|---|
Sun | Mon | Tue | Wed | Thu | Fri | Sat |
27 | 28 | 29 | 30 | 31 | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Javascript 中几种数组赋值的区别及=号的作用
Javascript中,目前要把一个数组的内容等于另一个数组,我会的手段大致有三种:
1. a = b;
2. a = b.slice(0);
3. b.forEach(function(element){ a.push(element);});
这三种有什么不同呢?
这三种写法的不同究其原因都出在=号的作用上。数组间的等号可以认为是一个别名。也就是 a = b 的效果等同于 b.alias => a, 给 b 取了个叫a的别名。数组还是同一个数组,多了个名字而已。于是不论用名字 a 操作还是用名字 b 操作,改变的都是同一个数组,换个名字都能看到效果。比如:
var b = [1]; var a = b; a.push(2); b.push(3); console.log(a); //[1,2,3] console.log(b); //[1,2,3]
而 b.slice(0) != b 本身, 只是等于 b 的内容。 a = b.slice(0); 相当于先 new 了一个新的匿名 array,内容为 b 的内容,然后取了个名字叫 a。因为是new出来的,所以用 a = b.slice(0) 后,操作 a 和操作 b 是操作两个不同的数组。
那么,什么时候用第三种呢?要用第三种,很明显,首先 a 必须是一个已经存在的数组,不然会报 undefined。第三种的使用场景有比如这样的:
var a = []; var b = [1]; var c; afunction(a){ c = a;}; //一个函数,使用a作为传入参数,只调用一次 //此时想把 b 的值赋给c。
因为 c 只在函数体内才能被赋值,而这个值只能通过a来进行。 如果用 a = b, 那么效果等同于 (Original Array a) . removeName(a), 然后 b.alias(a); 而 c 依然是那个 Original Array a,只是丢失了原本a这个名字,只剩下c这个名字了。类似的,如果用 a = b.slice(0), 也无法改变c,只是让c这个数组丢失了另一个叫a的名字而已。这时候,用第三种,把 b 的内容逐个加到已有的 a 里面,才能同时操作到 c。
装了个Octave
装了个Octave,用来做些题目。但是遇到了一些问题,结果不是很理想。
先是在Linux下装的。用的Gentoo,有些USE是去掉的。于是乎,最后装好的样子就是不能生成图形,也不能看help。不能生成图形是有心理准备的,因为我的Gentoo连X都没装,gtk 和 qt 也都是去掉的。不能生成help则是因为doc这个USE Flag被去掉了。如果加回去,则需要装很大一堆包,包括几个X的和几个Tex的,感觉太小题大做了。
于是,加上看着这个软件的计算功能还不错,本着用来代替Windows自带计算器的想法,准备装到Windows上去。我用的Windows8,使用了那个for VS2010的setup.exe来安装。装好后不能用…… 一查,发现这个在Windows8下还需要做点fix,需要在启动的时候加一个 -i --line-editing。 于是乎,加了,然后再打开。这下基本可以正常用了。可惜,想用于代替calc还是不太靠谱。原因无它,速度太慢了。打开慢,生成图像也慢。几十秒才能出结果,这简直无法接受。
但是我看别人好像并没有遇到“慢”的问题。不知道原因何在。是因为Windows8?还是因为我的jre不太对?我的jre装完后,只能执行java,一旦输入java -v 会直接告诉你不能生成VM,让人很囧。
我还有一台Windows8.1的机器,一会去试试看能否有改观。
Total War: Rome II Pack file Specification
From 00h
Header:
4 bytes String "PFH4" -----PFH0 in ETW, NTW and S2TW, sometimes PFH1, but now it is PFH4.
4 bytes Int32 PackType ------ In R2TW, all the types so far have appeared are 40, 01, 02, 11, 12
4 bytes Int32 IsPatch? ----- 1 means it is a patch or something of this kind, following another pack.
4 bytes Int32 Length Of the Name of the Pack it following
4 bytes Int32 Amount of File ---- Indicating how many files exist in this pack.
4 bytes Int32 Length of IndexTable -------IndexTable is the next section, contains all of the filenames and the length of every file.
4 bytes xx Unknown. ---- Maybe it means the 4 of "PFH4"
-----------------------------------------------------------------------------------
Optional: The Name of the Pack it following, exists only when the "IsPatch" is 1
n bytes String Name of the Pack it following. n = "Length Of the Name of the Pack it following "
-----------------------------------------------------------------------------------
IndexTable:
4 bytes Int32 Length of the File --------"the File" means the file associated with the filename directly followed.
n bytes Null-terminated ASCII String Filename ----------ended with a 0x00
.......... a "Length of the File" and a "Filename" is a group, presents the infomation of a file............
........... and this kind of group continues, until it meets the length that has been determined by "Length of IndexTable" in the Header section.............................
----------------------------------------------------------------------------------
Body:
n bytes binary Continuous File Data without alignment. ------------- n is determined by the "Length of the File" in IndexTable section, and so is one file.
............. Continue, till the end of pack.
近期的语音练习
最近,其实说近也不近,大致估算也有一年多了,对语音的兴趣十分浓厚,并勤于练习。大多数时间是在练习颤音,主要是拉丁语的颤音r。这个音在西班牙语和意大利语里面也有,西班牙语是rr,意大利语是r,以意大利的更标准一些。这个音练习到现在也没怎么练好。不断地练习、反馈、学习、琢磨之中,经常有新的发现。目前已经失去对“正音”的判断能力。我能发出跟各种视频,音频很相似的声音,但是各种视频、音频里面展示的发音各不相同,这让我很是困惑。有种说法是,Classic Latin 的读法中,但凡有r的地方,都是需要发颤音的。我听的Wheelock的前两课的词汇里面,确实也是这么做的。然而这样会让很多词变得非常难念。比如各种 -re结尾的就会很难听,而以 -r 结尾的更让人别扭。两者结合的诸如 conservare 这样的,单个词念一下也就罢了,放在句子里面经常让人卡住。LLPSI的音频里面,则是很多r 都念得跟英语的r 差不多,听不到明显的颤音。各种歌曲资料也难以参照。 Libera 之类的合唱团,完全是英语念法,倒是可以直接排除;帕瓦罗蒂那种就纠结了,他有些地方发得颤音很明显,有的地方又听不出来;美国的神童女 Jackie Evancho的颤音很到位,我感觉她的拉丁语发声都比她的英语要好了;意大利人的组合 Rhapsody,估计是意大利语的关系,颤音也很销魂,听起来感觉就是在舌头尖上打转的那种,而我则办不到这一点,造型部位要更接近上颚,弄得跟翘舌似的。
由颤音r引入的,我学习了很多关于语音的知识。比如英语的r跟汉语的r是不同的,西班牙语也有自己的一个r的念法。西班牙语不少发音都有自己的特点,d 就不能按照英语的 d 来念,粗听类似,但发声要领有区别。粗听都不同的也有,比如 j,发跟 英语 h 类似的音,不过又不是完全等于 h,跟英语的j则是完全不搭边。欧洲国家虽然大多都用拉丁字母,但各种字母的表音却各有一套,望文辩声完全不靠谱,由此我又进一步学习了IPA,企图能得到一个统一的表音符号体系。起初一切都良好,除了我不会在电脑上打出IPA符号,除了不少IPA符号表示的音我发声有困难辨析有困难之外都好。可是,再进一步了解之后,我发现这也是一个坑。不同年代不同版本的IPA符号经常互相混淆。傻傻分不清的音从r等少数几个开始有扩散的趋势。比如元音的i,比如元音的o。一个地方有一个地方的记法。就是那个 r ,在英语中的 r,不考虑各地口音,单单 英国RP口音的 r,都有好几种表示。有的写成 r,有的写成 ɹ,但是跟 ɹ 在一张表里也有一个 r ,两者不是同一个音啊。
在迈入了语音学的大门之后,其实我也不知道算不算入了门,姑且就算吧,之后,了解的概念越来越多了。什么尖团音啊,擦音啊塞音啊,清浊对立啊之类的。有些很容易学习很容易辨别,有些则困难些。比如清浊声,也就是voiceless 和 voice 的,汉语普通话没有清浊对立,只有送气和不送气的对立;英语则清音大多都送气,浊音都不送气。这样就很容易把汉语的送气不送气对立直接套用到英语清浊音里面,用送气与否来代替 voiceless 与否。实际上,汉语拼音里面的b跟英语里面的b是不同的,d跟d也不同,g和g也不同。了解到这个事实后,我经常在反省,到底我自己用的是正确的发音吗?我母语是吴语,对于清浊对立倒并没有障碍,吴语的 '把' 是清音b,'白' 是浊音 b,'搭'是清音d,'夺' 是浊音d。这个我在说吴语的时候可以发得自然和谐毫无压力,然而,沿用到汉语普通话的时候,我对于拼音b开头的,用的是清音吗?在说英语的时候,对于字母b开头的,我念的是浊音吗?我发现我两者都不能肯定…… 我逐渐发现,至少在讲英语的时候,我对于b开头的,有些时候用的是清音,多数时候用的是浊音,g开头的,清音更多些,d则比较混乱。我于是开始逐词逐词地训练,然而在念每个词的时候,心里都惦记着那一堆堆的发音规则,真心是件很累人的事情啊,连话都不会说了。所幸,目前貌似已经拥有了辨析出别人的发声是清还是浊的能力。比如这首姚斯婷的《走进莎莉花园》,她用的就是清音,让我听了巨别扭,有种心里发痒没得挠的感觉。不过这个未经严格检验,改天应当弄一些不送气清音和送气浊音来辨析。据说原始印欧语有不少音是送气浊音,比如bhrater,这种费劲的音我都不明白怎么发出来,估计当年的人说得也费劲,于是后来这bh就音变成了b,最后转化到了英语的brother。
写了这么多,其实今天原本就想记录一个新找到的网站来着…… http://www.uiowa.edu/~acadtech/phonetics/english/frameset.html 美国英语发音的详细图解+音频。图很不错,动态的,各种细节都涉及到了。
PLS-00801: Type xxxxxx has no MAP method 这到底是啥啊……
前段时间把一个查询效率很低的视图给改成了 带一个日期参数的函数,输入一个日期,返回相应的结果集。但是这样没能完整地复制视图原有的功能,比如给定一个日期区间的查询就做不到了。于是今天给扩充了一下,然后就遇到了这个该死的莫名其妙的PLS-00801.
代码呢是这样的:
create table stockstructure ( oc_date NUMBER(10) , exchange_type CHAR(4) , stock_code CHAR(12) , total_amount NUMBER(20,3), turnover_amount NUMBER(20,3) , remark VARCHAR2(2000 ) ); create or replace type rec_stockstructure is OBJECT( oc_date NUMBER(10 ) , exchange_type CHAR(4 ) , stock_code CHAR(12 ) , total_amount NUMBER(20 ,3), turnover_amount NUMBER(20 ,3) , remark VARCHAR2(2000 ) ); create or replace type ty_stockstructure is table of rec_stockstructure; create or replace function fn_get_stockstructure( p_oc_date hstype.HsDate, p_end_date hstype.hsdate default 0 ) return ty_stockstructure is tmp_stockstructure ty_stockstructure := ty_stockstructure(); rs_stockstructure ty_stockstructure := ty_stockstructure(); begin if p_end_date = 0 then select rec_stockstructure(p_oc_date,a.exchange_type,a.stock_code,a.total_amount,a.turnover_amount,a.remark) bulk collect into rs_stockstructure from stockstructure a where (a.oc_date,a.exchange_type,a.stock_code) in ( select max (t.oc_date),t.exchange_type,t.stock_code from stockstructure t where oc_date<=p_oc_date group by t.exchange_type,t.stock_code ) ; else for xdate in 0..(to_date(p_end_date,'yyyymmdd' )-to_date(p_oc_date,'yyyymmdd')) loop select rec_stockstructure(to_char(to_date(p_oc_date,'yyyymmdd' )+xdate,'yyyymmdd'),a.exchange_type,a.stock_code,a.total_amount,a.turnover_amount,a.remark) bulk collect into tmp_stockstructure from stockstructure a where (a.oc_date,a.exchange_type,a.stock_code) in ( select max (t.oc_date),t.exchange_type,t.stock_code from stockstructure t where oc_date<=to_char(to_date(p_oc_date,'yyyymmdd' )+xdate,'yyyymmdd') group by t.exchange_type,t.stock_code ) ; rs_stockstructure := rs_stockstructure multiset union tmp_stockstructure; --------------------- 报错位置 end loop ; end if; return rs_stockstructure; end;
然后就在我标着的位置给抛出了一个错误。错误原文如此:
Error: PLS-00801: internal error [*** ASSERT at file pdw4.c, line 2079; Type 0x0x2b89f96a66e0 has no MAP method.;
于是我就纠结了,这到底说的是啥呢?这几个关键字我连搜索都没法搜。而且更纠结的是,在Oracle 11g 上不报错,在 Oracle 10g 上报错。那么是版本问题嘛?我查了下,10g multiset 的支持完全没问题啊。我又在报错的这个数据库上做了个这样的测试:
select * from table( ty_stockstructure(rec_stockstructure(1234,'1','1234',1,1,'1')) multiset union ty_stockstructure(rec_stockstructure(2234,'2','2234',2,2,'2')) )
结果也是好好的,完全符合预期。真是无厘头啊,这都什么情况啊……
跪求一个证明我错了的用例……
这两天无聊刷HDOJ,各种不爽啊。C语言果然是忘记光了。
今天遭遇1003题。这题网上一搜倒是一堆讨论的,全是不知道自己死在哪的。而回复则大多是“这是一道典型/经典/简单的动态规划题”,然后给个AC的代码。我不知道动态规划是什么,当年学的时候没注意听就算听了现在也早忘记掉了,但是你给个正确的代码并不能表示我的就是错的啊…… 如果说错了,那么到底错哪里呢…… 跪求一个能证明我错了的测试用例……
HDOJ 1003 题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003
我的代码:
#include <stdio.h> int main(){ int times, numbers; long a, result, pretend; int i,j,s,e; scanf("%d",×); for(i=1;i<=times;i++){ scanf("%d",&numbers); scanf("%ld",&a); result = a; pretend = a; s = 1; e = 1; for(j=2;j<=numbers;j++){ scanf("%ld",&a); pretend += a; if(pretend>result){ result = pretend; e = j; } if(a>result){ result = a; s = j; e = j; } } printf("Case %d:\n%ld %d %d\n",i,result,s,e); if(i!=times){ printf("\n"); } } return 0; }
----- 2013.02.01 P.S.-------------------
因为不知道DP具体是个啥,今天抽空查了些资料,草草研究了下DP究竟是怎么回事,并参考了别人的一些代码,虽然错误用例还是没能找到。 我的代码的算法大致可以这样描述吧:
MaxSum[1] = ValueN[1];
MaxSum[n] = (MaxSum[n-1]+ValueN[n]>MaxSum[n-1]? MaxSum[n-1]+ValueN[n]: MaxSum[n-1]) > ValueN[n] ? $1: ValueN[n]
$1 表示 前一个判断得到的结果。
第一个判断 MaxSum[n-1] + ValueN[n] > MaxSum[n-1] ? 只要 ValueN[n] >0就能成立
第二个判断 MaxSum[n-1] + ValueN[n] > ValueN[n],成立条件是 MaxSum[n-1] > 0,第二个判断的另一个分支 MaxSum[n-1] > ValueN[n] 则不能直接看出正负关系,但是因为要走到这个分支,必然要求ValueN[n]为负,要小于一个负数的话,MaxSum[n-1] 必然也得是负数,这样才能让条件不成立从而得到ValueN[n]。换句话说,只要 MaxSum[n-1] >0, 第二个判断得到的结果都是 MaxSum[n-1] + ValueN[n] 或者 MaxSum[n-1]。
写成这样了之后,看上去好像也是个DP吧…… 不知道有没有高人能给分析分析。
要注意Perl系统变量值的变化
忘了专业点的说法怎么叫了,这里说的系统变量就是指那些 $_, $1, $# 之类的默认设置了的变量。一直以来被告诫要注意的是$_这个变量,一个while循环一个if判断什么的,有可能改变它的值。因为一直注意,倒也没遇到太大障碍。
今天栽在另一个变量上了,$1。语句是这样的:
s/$1/$hash{$1}/gi if /(\w+)/;
执行后发现总是被替换为空字符串。难道是 hash里面没值?我于是改成了:
s/$1/$hash{$1}/gi if (/(\w+)/ && defined $hash{$1} );
结果还是一样。
进行调试,把相关的值都打出来,发现各个值都取得完全没问题,唯独在 s/xxx/yyyy/gi 这步上出错了。
仔细观察了下substitution的形式特征,我想起来xxx这部分可以是regex的,比如我常用来交换位置的那种做法:
s/(xxx)(yyyy)/$2$1/g
在这样一句中,很明显 $1,$2的值由前面所决定。回到我出错的这句,估计也是这个原因了。第一个 $1,它取的if中的regex捕捉到的内容,第二个 作为hash的key的$1,它取的是xxx这个位置捕捉的内容。(话说xxx这个位置专业点的叫法是啥来着……)。做个实验验证下:
if (/(\w+)/ && defined $hash{$1} ){
$replacement = $hash{$1};
s/$1/$replacement/gi;
}
实验通过,这样果然管用。
个税的Oracle一句SQL算法
没啥技术含量,其实就是一个对 model 用法的练习……
WITH AAA AS ( select 0 AS start_value, 3500 AS end_value, 0.0 ratio from dual union select 3500 , 5000, 0.03 from dual union select 5000 , 8000, 0.1 from dual union select 8000 , 12500, 0.2 from dual union select 12500 , 38500, 0.25 from dual union select 38500 , 58500, 0.3 from dual union select 58500 , 83500, 0.35 from dual union select 83500 , NULL, 0.45 from dual ) SELECT (XX -start_value)*ratio + quick_num FROM ( SELECT start_value,decode(end_value, 0 , NULL ,end_value) AS end_value,ratio, quick_num FROM ( select row_number()over(order by start_value) rn, nvl(lag(end_value-start_value)over( order by start_value),0)*nvl(lag(ratio)over(order by start_value),0) quick_num, start_value, end_value,ratio from AAA ) a model dimension by (rn) measures (quick_num,start_value,end_value,ratio) IGNORE NAV RULES (quick_num[ ANY ] ORDER BY rn = quick_num[cv(rn)- 1] + quick_num[cv(rn)], start_value[ ANY ] = start_value[cv(rn)], end_value[ ANY ] = end_value[cv(rn)], ratio[ ANY ] = ratio[cv(rn)]) ) WHERE XX >= start_value AND ( XX < end_value OR end_value IS NULL )
XX为工资收入扣除各种保险和住房公积金后的数目。总共出现了三个XX,都需要替换。其实做个函数比较好,不过那就不是一句了。
mplayer在Gentoo下的默认显示语言
在Gentoo中使用mplayer遇到一个莫名其妙的问题,我的locale一律全是en_US.UTF-8, 输入 "mplayer" ,它给出的回显文字却全是中文的。查看了一下 mplayer 的USE标记,里面也没有任何跟 语言 有关的,安装时也没说要 LINGUAS 的。
我的LINGUAS设置的是“zh_CN zh_TW jp en”,看来看去就这里可能是原因所在,不然的话难道会是 时区? 于是实验了一下,把 LINGUAS 改成了 “en zh_CN zh_TW jp”,然后重新emerge 了一次,再输入mplayer,这次它给的回显就正常了,全是英文了。
这个特性很坑爹,记录一下。
改了个WOW插件-法师自动补全施法材料
开始重操旧业玩起了WOW,只不过这次玩的是法师。法师有三种施法材料:魔粉,传送符文,传送门符文。用光了会被人质疑为不够专业。材料在包裹里20个一组占一个格子,所以一次买的时候最好买齐20个,省的老是回来补。手动买其实也没啥不方便的,不过能自动还是自动吧,懒人自然有懒想法。
这个功能倒是很常见的功能了,从古到今,带这功能的各种插件和宏都流传了不少。不过我这不是没装嘛。特地去为了这点事情而找个东西,实在太费劲了,不如自己直接添上。我在已经装了的一个叫AutoRepair的插件上开始修改。AutoRepair,顾名思义就是自动修理装备用的,修理装备会需要打开商店界面,用到MERCHANT_SHOW这个事件,这样就省得我自己去注册了。
遇到一段跑起来费解的代码
今天校准数据库的时候,发现了一个执行结果不同的现象。经过定位,发现问题出在下面这段代码上。这段代码的执行结果被一个v_request_num的变量所左右。 v_request_num 越小,最后的结果就越少, v_request_num 越大,最后的结果就越多。如果说单次执行的话,这个是废话。但多次执行,直到将表中数据计算完毕后的结果也是这样,着实费解。
Fundjour的数据结构
先设计好数据结构,然后在数据库里把表建立起来。这样即使前端部分还在写,我一样可以通过直接操作SQL来记录需要记录的东西,可以给前端部分的开发更多的时间。
一条记录的字段应当大致有这样几个:
ID 作为每笔收支的真正的标识符
DATE 日期
TIME 时间
BALANCE 数额
TYPE 币种
IO 收或支,标记一个方向
FT From/To,记录从哪里来或者到哪里去
USAGE 用途,缘由
日期和时间那里是分开还是合并呢?各有优劣。暂时先决定分开吧,以后看情况。
以上是一条记录应当有的结构。如果建表的话,还需要加入两个字段,一个是表主键,一个是记录的时间。加入表主键而不使用记录的那个ID是因为我想让记录的ID保持紧凑中间不要跳号。表主键就无所谓了。不过这点也许还需要再考虑。 加入记录时间则是因为发生时间和记录时间肯定会不一致的。都在当天也就罢了,要是隔天记录的话,只有一个时间会让统计失去意义的。
最后应当大致如此:
CREATE TABLE fundjour (
ID int , --- primary Key
RID int, -- record id
DATE date ,
TIME date,
BALANCE number,
TYPE varchar,
IO int,
FT varchar,
USAGE varchar,
RECORD_TIME date default sysdate -- 记录时间
)
准备写个记账用的东西
准备写个记账用的东西,不然不利于培养理财意识。已经半只脚在金融界的了,总得专业点吧。
带图形界面的编程是我的弱项,短时间内根本没法解决,索性回避吧。直接写个命令行操作的,用起来也能更省事更随心所欲一些。
这个东西的要求首先得要足够简洁和方便。每次打字一定要足够少。不然我直接往数据库里写SQL,功能还能更强大更灵活一些。然后得足够地灵活,不要太死板地限制我的输入。虽然多数时候我要求打字少,但也应当支持我话痨的时候。这个东西的功能暂时不需要太多,太多我也想不出来,只要基本的吧。大致应该有以下几个:
1. 资金来往记录的增删查改。
2. 各种分类统计功能。
技术选型还没想好。是把账目都写在文本里面还是弄到数据库里面去也没想好。这个一边做一边考虑吧。先描绘下想要的效果:
1.名字初定为fundjour,命令行输入fdj可调出。
2.调出来的当以 fdj > 打头,其后可输入具体指令操作。
2.1. 操作的指令不要写死,应当有一张列表,可随时修改。
2.2. "fdj > got 3000RMB: expense of Sep." 类似这样的一条表示入账了3000块。冒号后面为原因。这个冒号后面为因由就定死吧,太灵活的话写起来会比较困难。
2.3. 因为操作指令不写死,那么自然应当支持多种同义词。比如说 "fdj > add 3000RMB"
2.4. 应当支持多点废话,比如说"fdj > I got 3000RMB from company for expense of Septempber"。 这里应当能够正确识别出关键字"got","from","for"。 当然这个要先写到操作指令列表里面去。最前面那个纯废话的"I",应当能被无视。
2.5. 是否应当支持颠倒的顺序呢?还在犹豫…… 比如说 "From company I got 3000RMB as expense of September", 这样的应当可以支持吧,但是那个"I" 在这里会比较碍事。 而另一种比如说"Company paid me 3000RMB as expense of September" 这样的,我暂时没办法解析了。算了,颠倒顺序这点就先砍掉吧,等我在自然语言处理上有所成了再回炉。
3. 应当支持直接以命令方式使用,不需要先行进入fdj > 的shell。 命令方式的格式如下:fdj [detail]。比如说" fdj got 3000RMB "。 如果 [detail]为空白,那么默认显示当前月份的账目。
4. 上面写的时候设想的场景都是增加一条记录的,但这个是最简单的。其他的查删改都要难一些。查的话,关键操作符还是一样,由列表指定,具体查询条件应当支持 (1)时间和时间段,(2)缘由的模糊匹配,(3)大致的类别,(4)金额区间,(5)入账出账,(6)分类统计的输出。 具体怎么实现是个问题,就连怎么区分这6类也是个需要考虑的问题。给六类分别指定个不同的指令么?还是带参数?还是统统写在一起让它自己解析?
5.删除功能不需要太灵活。删除的作用本质上是删掉误输入的记录。就给两种格式吧:(1)删除上N条。或者删除上N至M条,或者删除上N,M,X,Y,Z条,或者多个区间。(2)删除记录的某个ID号,某个ID区间,某几个ID号,某几个ID区间。
6.修改功能还没想好。感觉这东西要按命令行的方式来操作的话有点类似在ed中编辑一样,会很憋屈。要不要考虑把那要改的记录搞进vim里,然后改完保存了再提交回去呢?
7. 各种查询统计,也放到指令列表里,对应到具体的统计方式。这货应当是个不断扩展的,光凭现在想必然没法想全了。到时候想到一个加一个进去吧,方便扩展。
从上面看,似乎不用数据库不太现实了。那就弄个数据库吧。前端把字符处理完后,将真正的内容都整进数据库里,然后到数据库里编辑各种统计的业务逻辑,给前端调用,大致就这么个方式吧。只不过这样一来,跨数据库平台就不太好跨了。算了,反正也就我自己用用,不跨也不要紧。SQLite不知道支不支持存储过程,要足够强大的话就用它;要是不行的话就用PostgreSQL。 Oracle虽然好并且我熟悉,但是Gentoo上安装会有麻烦。
前端的输入字符处理会是个难点,具体怎么实现我还得好好想想……
修改PLSQL.vim
" SQL au BufNewFile,BufRead *.sql call s:SQL() func! s:SQL() if exists("g:filetype_sql") exe "setf " . g:filetype_sql else setf sql endif endfunc
" Various types of comments. if exists("c_comment_strings") syntax match plsqlCommentSkip contained "^\s*\*\($\|\s\+\)" syntax region plsqlCommentString contained start=+L\="+ skip=+\\\\\|\\"+ end=+"+ end=+\*/+me=s-1 contains=plsqlCommentSkip syntax region plsqlComment2String contained start=+L\="+ skip=+\\\\\|\\"+ end=+"+ end="$" syntax region plsqlCommentL start="--" skip="\\$" end="$" keepend contains=@plsqlCommentGroup,plsqlComment2String,plsqlCharLiteral,plsqlBooleanLiteral,plsqlNumbersCom,plsqlSpaceError syntax region plsqlComment start="/\*" end="\*/" contains=@plsqlCommentGroup,plsqlComment2String,plsqlCharLiteral,plsqlBooleanLiteral,plsqlNumbersCom,plsqlSpaceError else syntax region plsqlCommentL start="--" skip="\\$" end="$" keepend contains=@plsqlCommentGroup,plsqlSpaceError syntax region plsqlComment start="/\*" end="\*/" contains=@plsqlCommentGroup,plsqlSpaceError endif syn sync ccomment plsqlComment syn sync ccomment plsqlCommentL
syntax region plsqlCommentLP start="PROMPT" skip="\\$" end="$" keepend contains=@plsqlCommentGroup,plsqlSpaceError syn sync ccoment plsqlCommentLP
HiLink plsqlCommentLP Operator
syn match plsqlStringLiteral "'\([^']\|''\)*'"
syn region plsqlStringLiteral start="'" end="'"
原来function里可以DML的
一直以为function里面是不能做除了Select之外的DML的,除了自治事务,并将其当作与Procedure的主要区别。这个从道理上也是讲的通的,因为function应当具有被多次执行而结果一致的特点,倘若做了insert,delete,update之类的事情,每次执行结果必然不同。因此,我坚信不移了。
没想到,今天在查阅同事写的已有的系统模块时,发现他的大量function都是带着Insert,update等操作的,并且还有OUT类型的参数!与procedure的唯一区别仅仅在于多了个return的值。当时我就疑问了,这执行不报错吗?我想顺手写个语句测试下,却发现带有out类型参数的,我都没法直接写SQL。于是乎,我自己另行写了个:
CREATE FUNCTION insert_new( new_val IN NUMBER) RETURN NUMBER IS BEGIN INSERT INTO testtable(col) VALUES( new_val); return 1; END insert_new;
然后用SQL调用:
SELECT insert_new(1) FROM DUAL;
如我所料,报错了,说不能执行这类DML云云。
带着我的疑问,去找同事询问。他表示,可以执行啊。然后边说边打开了一个PLSQL DEVELOPER的Test Window,输入几个参数,然后点击执行,居然果真成功执行了。
仔细观察了两个结果,最后终于发现了不同点。Test Window所用的是一个PLSQL Block,用了赋值语句来接收函数值。我仔细查了查书,发现书上原来写的也很清楚,长期以来我所坚信的那些限制都只是“在SQL中调用自定义函数”的限制,在PLSQL Block中并不适用。
好多误区
为了准备面试,好好地恶补了一下PLSQL,连带着Oracle的一些机制。对于过去遗留的问题,也详细查找实验了一番,结果发现好多误区和讹传。可能那些说法在刚出来的时候是对的吧,但是随着版本的发展,很多早就已经不适用了。可惜网络上还是充斥着这些内容。有些是过去的遗留,还有很多是听信了那些过时结论又没实验,而却当作“答案”新近告诉别人的,这种影响极为恶劣。一看日期,人家都还以为现在这个时代依然如此呢,相当容易误导。
首先先说一个常见的关于复合索引的认识。很多地方关于复合索引都有这么种说法:复合索引按建立时排的顺序排在最前面的是引导列,当查询条件是引导列在最前时,走索引,否则不走;如果多个复合索引列在查询条件中顺序乱了也不走;如果中间跳过一个,我看到两种说法,一种说不走,一种说可以跳跃着走索引。
这样描述可能不清楚,举个实际例子:
CREATE TABLE tb( a number, b number, c number);
CREATE INDEX idx ON tb(a,b,c);
以上说法认为:
几个面试题
本来今天去面试动机就不纯,基本只是为了积累经验锻炼队伍去的,所以答得怎么样都无所谓了。不过第一眼看到笔试卷的时候,还是很庆幸:遇到简单题了。想象中的关于数据库各种机制的深刻挖掘基本没有,一些复杂类型的复杂用法也没有。总共12道题目,做完后感觉良好,有80%把握能对,不过现在回想一下,还是有不少题目答错了,或者答得不够好。
这笔试卷上来是几道我事后查了一下所谓的华为的面试题。
题:什么是事务?
这个要说我不知道什么是事务那真叫冤枉。但让我写,我却想不起来怎么个写法。最后只能走曲线,表示一次rollback/commit/rollback to savepoint到一次rollback/commit/rollback to savepoint 之间的那部分就是一个事务。事后查了下,原来这题的得分点在ACID上…… 原子性,一致性,隔离性,持久性。
整理一下Gentoo上让Mplayer在framebuffer中运行的设置过程
这两天一直在折腾。现在还在emerge kde-meta。这次基本是死磕状态,各种问题遇到一个解决一个,不留隐患。
要让mplayer能在framebuffer中运行,那么首先需要打开framebuffer。不知道该不该用“打开”这个词,反正就那个意思了。即便不准备在framebuffer中跑mplayer,只要没装X之类的东西,framebuffer也是很有必要开启的,因为原生的字体太大了,很多目录单纯ls一下都能超过屏幕边界,不得不再在后面加上 | less,可是这样一来颜色又没了。
打开framebuffer的话,主要就是编译内核,使之支持framebuffer。这部分昨天做的时候走了不少歪路,但最终发现还是应当按着Gentoo Wiki 上的相关说明 来做是最好的。
一开始是在内核中开启 “Support for frame buffer devices”,并启用下面的 firmware EDID
Device Drivers -> Graphics support ---> -*- Support for frame buffer devices ---> [*] Enable firmware EDID ... *** Frame buffer hardware drivers *** |
然后选择要开的framebuffer的类型。“类型”这个词可能也不准确,应该说不同的驱动吧。昨天走的歪路就在这里。因为我顺手点进了KMS下的设置,而上面说,应当禁用掉Frame buffer hardware drivers中所列的所有驱动,不然会有冲突。事实上我用的是nvidia的闭源驱动,根本不关KMS的事。
移动(cmpp协议)发送即显短信的设置
即显短信,也就是直接在手机屏幕上显示出来,不用自己点进去查看,同时看完之后直接就没了,不会留下短信记录的那种短信。在中国移动采用的SP与ISMG之间的CMPP协议中,发送消息使用的是CMPP_SUBMIT消息,该消息的消息体如下:
一个简单的改名备份脚本
虽然说打算在服务器上用版本控制来管理部署的程序了,但一时终归还没用起来。而按照惯例,上传新版时旧版是不删的,仅仅改个名字存放起来而已。改名字时也没啥严格规定,一直以来有点乱。当然也许别人重命名还是比较规矩的,但反正我是很随心所欲的,搞得经常自己也记不清楚,只能靠修改时间来辨认。上次写了个脚本,把给名字自动加上时间后缀作为备份命令,倒也还管用。这次想再改进一下,上点参数,能整成 "*.latest", "*.current", "*.last" 之类的效果。
#!/bin/bash case "$1" in "") echo "Usage: bak [option] filename" echo "bak: rename a file as a backup" echo "Try \"bak -h\" for help" exit ;; *) rename=0 option=0 while getopts "hrlc" flag do option=1 case "$flag" in "h") helplist=1;; "r") let "rename += 1";; "l") last=1;; "c") current=1;; esac done if [ "$option" -ne 1 ] then filename=$1 newfilename=$filename.`date +%Y%m%d%H%M` mv -f $filename $newfilename echo $newfilename exit fi ;; esac if [ "$helplist" = 1 ]; then echo "bak: rename a file as a backup" echo "Usage: bak [option] filename" echo "default(no option): rename filename to filename.`date +%Y%m%d%H%M`" echo "Options:" echo " -l: rename filename to filename.last" echo " -c: rename filename to filename.current" echo " -r: cut the end of filename from the last dot, example:" echo " filename.last --> filename" echo "multiple r will try to cut multiple part split by dot from the end, as:" echo " -rrr filename.section1.secion2.section3 --> filename" exit fi case "$2" in "") echo "Usage: bak [option] filename" echo "bak: rename a file as a backup" echo "Try \"bak -h\" for help" ;; *) filename=$2 newfilename=$filename if [ "$rename" -ne 0 ]; then for i in `seq 1 $rename` do newfilename=${newfilename%.*} done fi if [ "$last" = 1 ]; then newfilename=$newfilename.last elif [ "$current" = 1 ];then newfilename=$newfilename.current else newfilename=$newfilename.`date +%Y%m%d%H%M` fi mv $filename $newfilename echo $newfilename ;; esac