想必不少人聽(tīng)說(shuō)過(guò)javaagent,但是很少人聽(tīng)說(shuō)Instrumentation,其實(shí)Instrumentation就是javaagent的實(shí)現(xiàn)機(jī)制,說(shuō)到Instrumentation,就必須想了解java的attach機(jī)制,那就先說(shuō)下attach的實(shí)現(xiàn)。

大家進(jìn)行jstack的時(shí)候,是不是經(jīng)常看到兩個(gè)線程Signal Dispatcher和 Attach Listener線程,可能不知道是干嘛的吧,這兩個(gè)線程是實(shí)現(xiàn)attach的關(guān)鍵所在,其中前者是在jvm啟動(dòng)的時(shí)候就會(huì)創(chuàng)建的,后者只有接收過(guò)attach請(qǐng)求的時(shí)候vm才會(huì)創(chuàng)建,顧名思義,Signal Dispatcher是分發(fā)信號(hào)的, Attach Listener 是處理attach請(qǐng)求的,那么兩者有什么關(guān)系呢,當(dāng)我們執(zhí)行attach方法的時(shí)候,會(huì)向目標(biāo)vm發(fā)出一個(gè)SIGQUIT 的信號(hào),目標(biāo)vm收到這個(gè)信號(hào)之后就會(huì)創(chuàng)建Attach Listener線程了,當(dāng)然jvm保證了不會(huì)多創(chuàng)建。
1 path = findSocketFile(pid);
2 if (path == null) {
3 File f = new File(tmpdir, ".attach_pid" + pid);
4 createAttachFile(f.getPath());
5 try {
6 sendQuitTo(pid);
7
8 // give the target VM time to start the attach mechanism
9 int i = 0;
10 long delay = 200;
11 int retries = (int)(attachTimeout() / delay);
12 do {
13 try {
14 Thread.sleep(delay);
15 } catch (InterruptedException x) { }
16 path = findSocketFile(pid);
17 i++;
18 } while (i <= retries && path == null);
19 if (path == null) {
20 throw new AttachNotSupportedException(
21 "Unable to open socket file: target process not responding " +
22 "or HotSpot VM not loaded");
23 }
24 } finally {
25 f.delete();
26 }
27 }
Attach機(jī)制說(shuō)得簡(jiǎn)單點(diǎn)就是提供A進(jìn)程可以連上B進(jìn)程(當(dāng)然是java進(jìn)程),創(chuàng)建socket進(jìn)行通信,A通過(guò)發(fā)命令給B,B然后對(duì)命令進(jìn)行截取從自己的vm中獲取信息發(fā)回給客戶端vm,但是并不是隨便發(fā)指令都會(huì)處理的,那么attach Listener接收哪些命令呢,如下所示
static AttachOperationFunctionInfo funcs[] = {
{ "agentProperties", get_agent_properties },
{ "datadump", data_dump },
{ "dumpheap", dump_heap },
{ "load", JvmtiExport::load_agent_library },
{ "properties", get_system_properties },
{ "threaddump", thread_dump },
{ "inspectheap", heap_inspection },
{ "setflag", set_flag },
{ "printflag", print_flag },
{ "jcmd", jcmd },
{ NULL, NULL }
};
Instrumentation的實(shí)現(xiàn)其實(shí)主要使用了load這個(gè)指令,它用來(lái)實(shí)現(xiàn)讓target vm動(dòng)態(tài)加載agentlib,Instrumentation的實(shí)現(xiàn)在一個(gè)名為libinstrument.dylib的動(dòng)態(tài)lib庫(kù),linux下是libinstrument.so,它是基于jvmti接口實(shí)現(xiàn)的,因此在對(duì)其進(jìn)行l(wèi)oad的時(shí)候會(huì)創(chuàng)建一個(gè)agent實(shí)例,并往jvmti環(huán)境注冊(cè)一些回調(diào)方法,比如監(jiān)聽(tīng)類文件加載的事件,vm初始化完成事件等,執(zhí)行Agent_OnAttach,這里會(huì)創(chuàng)建一個(gè)Instrumentation實(shí)例并返回給用戶供大家擴(kuò)展Instrumentation,比如增加一些transform。并會(huì)執(zhí)行Instrumentation實(shí)例的loadClassAndCallAgentmain方法,該方法主要執(zhí)行agent的MF文件里定義的 Agent-Class類的agentmain方法,當(dāng)vm初始化完畢之后,會(huì)調(diào)用loadClassAndCallPremain方法,該方法主要執(zhí)行agent的MF文件里定義的 Agent-Class類的pre main方法。在類進(jìn)行加載的時(shí)候會(huì)調(diào)用Instrumentation的transform方法,可以看看參數(shù)里有個(gè)byte數(shù)組,這個(gè)數(shù)組其實(shí)就是正在加載的class字節(jié)碼,所以如果要字節(jié)碼增強(qiáng)在這里就可以入手啦,甚至可以實(shí)現(xiàn)偷天換日.
最近在忙一個(gè)項(xiàng)目,使用的是Flex+Spring+Hibernate,期間碰到一個(gè)問(wèn)題,有必要在此記錄一下,也方便有相似問(wèn)題的來(lái)者參考下
問(wèn)題描述:有一個(gè)用戶表和一個(gè)用戶詳情表,這兩個(gè)表是一個(gè)一對(duì)一的單向關(guān)聯(lián)關(guān)系,即在用戶表中一個(gè)外鍵引用用戶詳情表,我在UserInfo的映射文件中使用的是many-to-one,設(shè)置了unique="true"表示一對(duì)一關(guān)系,設(shè)置了cascade="save-update"表示的是在保存useInfo對(duì)象的時(shí)候會(huì)自動(dòng)保存與之關(guān)聯(lián)的userDetails臨時(shí)對(duì)象,即我希望的是先執(zhí)行一個(gè)在用戶詳情表中的插入語(yǔ)句然后再執(zhí)行一個(gè)在用戶表中的插入語(yǔ)句,userInfo對(duì)象是從flex端傳過(guò)來(lái)的,當(dāng)然也設(shè)置了userDetails屬性的值,在userInfo的dao文件中save方法是這樣的
public IvUserInfo save(IvUserInfo transientInstance) {
log.debug("saving IvUserInfo instance");
try {
getHibernateTemplate().save(transientInstance);
log.debug("save successful");
} catch (RuntimeException re) {
log.error("save failed", re);
throw re;
}
return transientInstance;
}
后面發(fā)現(xiàn)執(zhí)行的sql語(yǔ)句只有一條插入語(yǔ)句,就是在用戶表中的一個(gè)插入,由于外鍵的關(guān)聯(lián)作用,是用戶表的這條插入也無(wú)法執(zhí)行,這就是問(wèn)題所在了。
問(wèn)題解決:這個(gè)問(wèn)題我也沒(méi)有具體研究Hibernate的源碼,我先寫(xiě)了個(gè)測(cè)試類,發(fā)現(xiàn)僅僅在java中執(zhí)行操作的話是可以正確執(zhí)行兩條插入語(yǔ)句的,但是通過(guò)flex傳過(guò)來(lái)就有問(wèn)題了,那說(shuō)明是flex端傳參數(shù)過(guò)來(lái)的問(wèn)題,于是我試著修改UserInfo的save方法:
public IvUserInfo save(IvUserInfo transientInstance) {
log.debug("saving IvUserInfo instance");
try {
IvUserDetails ud=new IvUserDetails();
ud.setQq(transientInstance.getIvUserDetails().getQq());
transientInstance.setIvUserDetails(ud);
getHibernateTemplate().save(transientInstance);
log.debug("save successful");
} catch (RuntimeException re) {
log.error("save failed", re);
throw re;
}
return transientInstance;
}
這樣一來(lái)問(wèn)題解決了,順利執(zhí)行了兩條插入語(yǔ)句。
如果朋友知道具體原因的話希望給我留言了,同時(shí)也希望該記錄能幫助碰到此類問(wèn)題的朋友。
歡迎光臨筆者博客
http://www.lovestblog.cn
最近兩天本人在為本博實(shí)現(xiàn)rss發(fā)布和訂閱,本來(lái)是想在前端實(shí)現(xiàn)xml的生成和修改,因?yàn)橛胊s3的E4X操作xml比較方便,但是后面發(fā)現(xiàn)不能為元素設(shè)置CDATA值,于是只好作罷,便只能依靠后臺(tái)的java來(lái)實(shí)現(xiàn)此功能了,當(dāng)然操作xml的話,我首先想到了dom4j,dom4j操作xml還是比較方便的,即可以輕松實(shí)現(xiàn)我們的CDATA設(shè)置,也可以為我們?nèi)我馕恢貌迦朐靥峁┝藢?shí)現(xiàn),對(duì)于在指定位置新增節(jié)點(diǎn)開(kāi)始我有點(diǎn)蒙了,后面通過(guò)網(wǎng)上搜索資源加之自己的一些理解,而實(shí)現(xiàn)了此功能,下面展示了部分代碼供今后參考吧:
-

public static int createXMLFile(String filename,List list)
{

/** *//** 返回操作結(jié)果, 0表失敗, 1表成功 */
int returnValue = 0;
Document document = DocumentHelper.createDocument();
Element rssElement = document.addElement("rss");
rssElement.addAttribute("version", "2.0");
Element channelElement = rssElement.addElement("channel");
Element titleElement = channelElement.addElement("title");
titleElement.setText("你假笨(nijiaben)心情技術(shù)博客");
Element linkElement = channelElement.addElement("link");
linkElement.setText("http://www.lovestblog.cn");
Element descriptionElement = channelElement.addElement("description");
descriptionElement.setText("專注于Java,Flex技術(shù)開(kāi)發(fā)研究");
Element languageElement = channelElement.addElement("language");
languageElement.setText("zh-cn");
Element lastBuildDateElement = channelElement.addElement("lastBuildDate");
lastBuildDateElement.setText(new java.text.SimpleDateFormat("yyyy-mm-dd hh:mm:ss",Locale.CHINA).format(((ArticleInfo)(list.get(0))).getCreateTime()));

for(int i=list.size()-1;i>0;i--)
{
ArticleInfo ainfo=(ArticleInfo)(list.get(i));
Element itemElement = channelElement.addElement("item");
Element title1Element = itemElement.addElement("title");
title1Element.setText(ainfo.getTitle());
Element description1Element = itemElement.addElement("description");
int maxLen=5000;

if(ainfo.getRssContent().length()<5000)
{
maxLen=ainfo.getRssContent().length();
}
description1Element.addCDATA(ainfo.getRssContent().substring(0, maxLen));
Element pubDate=itemElement.addElement("pubDate");
pubDate.setText(new java.text.SimpleDateFormat("yyyy-mm-dd hh:mm:ss",Locale.CHINA).format(ainfo.getCreateTime()));
Element link1Element=itemElement.addElement("link");
link1Element.setText("http://www.lovestblog.cn");
}

try
{

/** *//** 將document中的內(nèi)容寫(xiě)入文件中 */
XMLWriter writer = new XMLWriter(new FileOutputStream(path+filename));
writer.write(document);
writer.close();

/** *//** 執(zhí)行成功,需返回1 */
returnValue = 1;

}catch(Exception ex)
{
ex.printStackTrace();
}
return returnValue;
}

本文最新發(fā)布于http://www.lovestblog.cn,歡迎轉(zhuǎn)載該文,但請(qǐng)注明文章出處,謝謝合作。
mysql的from從句用來(lái)指定參與查詢的表,當(dāng)然也可以是生成的中間表,在表前我們有時(shí)需要指定數(shù)據(jù)庫(kù),這主要是用在我們需要訪問(wèn)當(dāng)前數(shù)據(jù)庫(kù)之外的數(shù)據(jù)庫(kù)中的表的情況,在這中情況下我們采用"."操作符來(lái)進(jìn)行,如userdb.user,其實(shí)userdb為數(shù)據(jù)庫(kù)名,user為表名,這是對(duì)mysql數(shù)據(jù)庫(kù)而言的,對(duì)于DB2和Oracle就不是通過(guò)指定數(shù)據(jù)庫(kù)名了,而是指定sql用戶了,這就是說(shuō)不同sql用戶可以建立相同名字的表,但是同一個(gè)sql用戶只能建立唯一名字的表。這就是它們?cè)谶@表規(guī)范上面的區(qū)別。對(duì)于列規(guī)范,mysql可以在需要查詢的列則可以采用如下形式進(jìn)行訪問(wèn):“數(shù)據(jù)庫(kù)名.表名.列名”。對(duì)于多個(gè)表的規(guī)范,也就是涉及查詢多個(gè)表的情況下,執(zhí)行的過(guò)程是采用笛卡爾積的形式進(jìn)行的。也就是說(shuō)生成的中間表的列數(shù)為兩個(gè)表中列數(shù)的總和,而行的總數(shù)等于一個(gè)表中的行的數(shù)量與另外一個(gè)表中行的數(shù)量的乘積。
對(duì)于from從句中使用假名的情況,比如select u.id,name,age,a.account from utb as u,atb as a where u.id=a.user_id,在我們使用假名之后,那么在該sql語(yǔ)句的任何地方都只能使用假名,不能使用真實(shí)的表名,同時(shí)上面的as關(guān)鍵字也是可以省略的,也就是說(shuō)對(duì)于上面的語(yǔ)句不能用atb來(lái)取代a,utb來(lái)取代u了。雖然from從句不是我們指定的第一條語(yǔ)句,但是絕對(duì)是第一個(gè)被處理的語(yǔ)句,所以在聲明假名前使用假名不會(huì)導(dǎo)致錯(cuò)誤。如果一條from從句引用到兩個(gè)有著相同名稱的表,則必須使用假名。如:
1
select p.playerno
2
from players as p,players as par
3
where par.fn="jp" and par.ln="l" and p.birth_date<par.birth_date
對(duì)于多個(gè)表間的連接處理可能會(huì)導(dǎo)致有相同的結(jié)果,即有重復(fù)的結(jié)果,sql并不會(huì)自動(dòng)從最終結(jié)果中刪除重復(fù)的行,這是如果我們不希望在結(jié)果中出現(xiàn)重復(fù)的行,那么我們可以在select后直接指定distinct。如:
1
select distinct T.playerno
2
from teams as T,penalties as pen
3
where T.playerno=pen.playerno。
接下來(lái)說(shuō)說(shuō)連接哈,對(duì)于內(nèi)連接,如果是兩個(gè)表的話,就取兩個(gè)表的一個(gè)交集,如果是左外連接的話,那就是左邊的表全取,右邊沒(méi)有的用null替代,弱國(guó)是右外連接的話,那就是右邊的表全取,左邊沒(méi)有的用null表示。下面看看一個(gè)具體的例子:
1
--表stu --表exam
2
id name id grade
3
1, Jack 1, 56
4
2, Tom 2, 76
5
3, Kity 11, 89
6
4, nono
內(nèi)連接 (顯示兩表id匹配的)
1
select stu.id,exam.id,stu.name, exam.grade from stu (inner) join exam on stu.id=exam.id
2
--------------------------------
3
1 1 Jack 56
4
2 2 Tom 76
左連接(顯示join 左邊的表的所有數(shù)據(jù),exam只有兩條記錄,所以stu.id,grade 都用NULL 顯示)
1
select stu.id,exam.id,stu.name, exam.grade from stu left (outer) join exam on stu.id=exam.id
2
1 1 Jack 56
3
2 2 Tom 76
4
3 NULL Kity NULL
5
4 NULL nono NULL
右連接(與作連接相反,顯示join右邊表的所有數(shù)據(jù))
1
select stu.id,exam.id,stu.name, exam.grade from stu right join exam on stu.id=exam.id
2
1 1 Jack 56
3
2 2 Tom 76
4
NULL 11 NULL 89
內(nèi)連接取交集,外連接分左和右,
左連接左邊的全取,
右連接右邊的全取
對(duì)于連接的列的名稱相同的話,那么可以使用using來(lái)替代條件,如上面的內(nèi)連接可以這樣改寫(xiě):
1
select stu.id,exam.id,stu.name, exam.grade from stu inner join exam using(id)。
對(duì)于左外連接使用的情況一般是當(dāng)左表的連接列中存在未出現(xiàn)在右表的連接列中的值時(shí),左外連接才有用。
還有個(gè)全外連接的,也就是說(shuō)只要在兩個(gè)表中出現(xiàn)的記錄都會(huì)在中間表中出現(xiàn),當(dāng)右表有而左表沒(méi)有或當(dāng)左表有而右表沒(méi)有的時(shí)候用null表示。具體語(yǔ)法如下:select stu.id,exam.id,stu.name, exam.grade from stu full join exam using(id)。
交叉連接:就是顯示求表的笛卡爾積,select * from teams cross join penalties.這句完全等價(jià)于select teams.*,penalties.* from teams,penalties.
聯(lián)合連接:select * from teams union join penalties,這個(gè)其實(shí)很容易理解,產(chǎn)生結(jié)果所包含的列為兩個(gè)表所有的列和,對(duì)于數(shù)據(jù)的列出,首先列出左表的數(shù)據(jù),對(duì)于屬于右表的列,用null表示,接下來(lái)列出右表的數(shù)據(jù),對(duì)于屬于左表的列用null表示。
自然連接:select * from teams nature inner join penalties where division='first';此句完全等同與select t.playerno,t.teamno,t.division,pen.paymentno,pen.payment_date,pen.amount from teams as t inner join penalties as pen on t.playerno=pen.playerno where dividion='first'.相比就知道,我們無(wú)須顯示指出必須要連接到哪些列,sql會(huì)自動(dòng)查找兩表中是否有相同名稱的列,且假設(shè)他們必須在連接條件中使用。此處的on或using從句是多余的,因此不允許使用。
下面看個(gè)例子創(chuàng)建一個(gè)稱為towns的虛擬表:
1
select *
2
from (select 'Stratford' as town,4 as number
3
union
4
select 'Plymouth',6
5
union
6
select 'Inglewood',1
7
union
8
select 'Douglas',2) as towns
9
order by town;
結(jié)果為:
1
town number
2
----------------------
3
Douglas 2
4
Inglewood 1
5
Plymouth 6
6
Stratford 4
本文最先發(fā)布于
http://www.lovestblog.cn,請(qǐng)轉(zhuǎn)載的該文者注明文章出處,謝謝合作。
下面簡(jiǎn)單介紹幾種標(biāo)量函數(shù),也是常用的,我們可以通過(guò)類似select abs(-123);的語(yǔ)句來(lái)看到我們標(biāo)量函數(shù)的效果。
abs:該函數(shù)返回一個(gè)數(shù)值表達(dá)式的絕對(duì)值。如abs(-123);
adddate:該函數(shù)將一個(gè)時(shí)間間隔(參數(shù)2)添加到時(shí)戳或時(shí)戳表達(dá)式(參數(shù)1)中,與此函數(shù)同功能的還有date_add。如adddate('2009-01-01',4);結(jié)果為2009-01-05。adddate(2009-01-01,interval 5 month);結(jié)果為2009-06-01。adddate(timestamp('2009-01-01'),interval 5 month);結(jié)果為2009-06-01 00:00:00。adddate('2009-01-01 12:00:00',interval 5 day);結(jié)果為2009-01-06 12:00:00。
addtime:把兩個(gè)時(shí)間表達(dá)式加起來(lái)。如addtime('100:00:00','200:02:04');結(jié)果為300:02:04。
ascii:該函數(shù)返回一個(gè)字符串表達(dá)式的第一個(gè)字符的ASCII值。
bin:該函數(shù)將參數(shù)的數(shù)值轉(zhuǎn)換為二進(jìn)制值。
bit_count:該函數(shù)顯示表示參數(shù)的值的位數(shù)。如bit_count(3)結(jié)果為2。
bit_length:該函數(shù)返回字符串值的位長(zhǎng)度。如bit_length(bin(2));結(jié)果為16
ceiling:該函數(shù)返回大于或等于參數(shù)值的最大整數(shù)。如ceiling(11.11);->12。ceicling(-11.11);->-11
char:該函數(shù)返回?cái)?shù)值參數(shù)的字符串字符,與此函數(shù)同功能的還有chr函數(shù)。如char(82)+char(105)+char(99)+char(107);->'Rich'
character_length:該函數(shù)返回一個(gè)字符串表達(dá)式的長(zhǎng)度,此方法同功能的還有char_length函數(shù)。
charset:該函數(shù)返回字符串參數(shù)的字符集的名稱。
coalesce:該函數(shù)接受多個(gè)參數(shù),返回第一個(gè)非null值的參數(shù)的值。如coalesce(null,null,'ljp');->'ljp';
concat:該函數(shù)合并兩個(gè)字符串的值。
conv:該函數(shù)將一基數(shù)為參數(shù)2的值(參數(shù)1)轉(zhuǎn)換為另一個(gè)以參數(shù)3為基數(shù)的值。如conv(1110,10,16)表示將以10進(jìn)制的數(shù)1110轉(zhuǎn)換成16進(jìn)制值為456。后面兩個(gè)參數(shù)必須介于2~36之間,否則結(jié)果為null,此外參數(shù)1的值應(yīng)該匹配參數(shù)2的基數(shù),否則結(jié)果為0。
convert:該函數(shù)轉(zhuǎn)換參數(shù)1的數(shù)據(jù)類型為參數(shù)2指定的類型。參數(shù)2必須是一種數(shù)據(jù)類型,包括binary,char,date,datetime,time,signed,signed integer,unsigned,unsigned integer,varchar。如convert('12.56',unsigned integer);->13。
database:該函數(shù)顯示當(dāng)前數(shù)據(jù)庫(kù)的名稱。
date:該函數(shù)將參數(shù)變換為一個(gè)日期值。如date('2009-01-01 12:00:00');->'2009-01-01'。
datediff:該函數(shù)計(jì)算兩個(gè)日期或時(shí)間戳表達(dá)式間的天數(shù)。第一個(gè)參數(shù)減去第二個(gè)參數(shù)。
date_sub:該函數(shù)從一個(gè)日期或時(shí)間戳表達(dá)式(參數(shù)一)中減去一個(gè)時(shí)間間隔(參數(shù)2),與才函數(shù)同功能的還有subdate函數(shù)。
day:該函數(shù)從一個(gè)日期或時(shí)間戳表達(dá)式中返回月的天數(shù),結(jié)果總是介于1~31之間的整數(shù),與此函數(shù)同功能的還有dayofmonth。
dayname:該函數(shù)從一個(gè)日期或時(shí)間戳表達(dá)式中返回一周中某天的名稱。
dayofweek:該函數(shù)返回一個(gè)日期或時(shí)間戳表達(dá)式中返回某周的天數(shù)的序號(hào)。該結(jié)果總是介于1~7之間的整數(shù)。
dayofyear:該函數(shù)返回一個(gè)日期或時(shí)間戳表達(dá)式中返回一年中某日的序號(hào)。
default:該函數(shù)返回參數(shù)指定的某列的默認(rèn)值。
floor:該函數(shù)返回小于或等于參數(shù)值的最小整數(shù),與ceiling相對(duì)。
exp:該函數(shù)返回e的x次幕的結(jié)果。
format:該函數(shù)將一個(gè)數(shù)值的格式設(shè)置為nn,nnn,nnn.nnn的格式。第二個(gè)參數(shù)表示小數(shù)點(diǎn)后的數(shù)字個(gè)數(shù)。
greatest:該函數(shù)返回一系列參數(shù)中的最大值,和least相對(duì)。
hex:如果參數(shù)為數(shù)字,那么就返回該數(shù)字的十六進(jìn)制表示;如果是字符串,那么將返回每個(gè)字符對(duì)應(yīng)的ASCII碼。
if:如果第一個(gè)參數(shù)值為true,那么函數(shù)返回第二個(gè)參數(shù)的值,否則返回第三個(gè)參數(shù)的值。如if((1>2),"ljp","st");將返回st。
ifnull:如果參數(shù)1的值為null,那么返回參數(shù)2的值,否則返回參數(shù)1的值。如ifnull(null,"ljp");返回"ljp"。
insert:參數(shù)4的值放在參數(shù)1中由參數(shù)2指定的位置,參數(shù)3表示參數(shù)1中從參數(shù)2指定的位置開(kāi)始接下來(lái)的幾個(gè)字符將被參數(shù)4取代。如insert('abcdefgh',4,3,'zzz');->'abczzzgh'。insert('abcdefgh',,4,2,'zzz');->'abczzzfgh'。insert('abcdefgh',4,0,'zzz');->'abczzzdefgh'。insert('abcdefgh',4,-1,'zzz');->'abczzz'。insert('abcdefgh',1,5,'zzz');->'zzzfgh'。
instr:該函數(shù)返回參數(shù)1內(nèi)參數(shù)2的起始位置。如果為找到,則返回0。如instr('12345',4);->4。
interval:該函數(shù)第一個(gè)參數(shù)指定要插入的值,接下來(lái)的參數(shù)組成一個(gè)升序序列,看第一個(gè)參數(shù)該插入哪個(gè)位置。該函數(shù)就是返回該位置。如interval(5,0,1,2,3,6,7);->4表示要把5放在第四個(gè)位置(此位置上值為3)之后。
isnull:如果參數(shù)值為null,那么返回1,否則返回0。
last_day:該函數(shù)返回參數(shù)指定的日期或時(shí)間戳表達(dá)式中月的最后一天,如last_day('2009-01-09');->'2009-01-31'。
lcase:該函數(shù)將參數(shù)的值的所有大寫(xiě)字母轉(zhuǎn)換為小寫(xiě)字母,與lower同義,與ucase相對(duì)。
left:該函數(shù)返回一個(gè)字符串值參數(shù)1的左側(cè)部分,該部分的長(zhǎng)度由第二個(gè)參數(shù)指定。如left("hello world",3);->'hel'。
length:該函數(shù)返回一個(gè)字符串值的字節(jié)長(zhǎng)度。如length(null);->null。
ln:該函數(shù)返回參數(shù)的自然對(duì)數(shù),與log同義。
localtime:該函數(shù)返回系統(tǒng)日期和時(shí)間,localtimestamp與只同義。
locate:該函數(shù)返回參數(shù)1在參數(shù)2內(nèi)的起點(diǎn)位置。如果參數(shù)1在參數(shù)2內(nèi)未出現(xiàn),則返回0。參數(shù)3表示開(kāi)始搜索的位置。注意instr函數(shù)的區(qū)別,instr函數(shù)是返回參數(shù)1內(nèi)參數(shù)2的開(kāi)始位置。
log2:返回參數(shù)以2為底的對(duì)數(shù)。如log2(64);->6
log10:返回參數(shù)以10為底的對(duì)數(shù)。
lpad:參數(shù)3的值填充在參數(shù)1的左側(cè),直到該值的總長(zhǎng)度等于參數(shù)2的長(zhǎng)度。如果最大長(zhǎng)度小于參數(shù)1的長(zhǎng)度,則參數(shù)1在左側(cè)被截取。如lpad('data',6,'base');->'badata'。lpad('data',2,'base');->'da'。
ltrim:該函數(shù)刪除出現(xiàn)在參數(shù)前的所有空白,rtrim表示刪除參數(shù)末尾的所以空白。
makedate:參數(shù)2表示天數(shù),他們被添加到參數(shù)1中。如makedate(2009,10);->'2009-01-10'。
maketime:三參數(shù)分別表示小時(shí),分鐘,秒鐘。其中分鐘和秒鐘必須在0~59之間,否則會(huì)返回null。
mid:該函數(shù)提取參數(shù)1中的部分字符串值,參數(shù)2標(biāo)識(shí)開(kāi)始位置,參數(shù)3標(biāo)識(shí)字符數(shù)。如mid('database',5);->'base'。mid('database',5,2);->'ba'。mid('database',-6);-> 'tabase'。mid('database',-6,3);->'tab'。
minute:該函數(shù)從一個(gè)時(shí)間或時(shí)間戳表達(dá)式中返回分鐘數(shù)。
mod:該函數(shù)返回兩參數(shù)相除的余數(shù)。如mod(15.4,4,4);->2.2
month:返回時(shí)間戳中的月份數(shù),值介于1~12之間。
monthname:該函數(shù)從一個(gè)日期或時(shí)間戳表達(dá)式中返回月的名稱。如monthname('2009-01-01');->‘April’。
now:返回系統(tǒng)日期和時(shí)間。
nullif:如果參數(shù)1的值等于參數(shù)2的值,那么函數(shù)返回null。否則返回參數(shù)1的值。
oct:該函數(shù)返回八進(jìn)制參數(shù)1的十進(jìn)制數(shù)。如oct(8);->10
ord:該函數(shù)返回參數(shù)指定的字符串表達(dá)式的第一個(gè)字符的字符集位置。如ord('Das');->68。
period_add:該函數(shù)將月數(shù)添加到一個(gè)指定的日期,日期格式必須為YYYYMM或YYMM。結(jié)果格式為YYYYMM。如period_add('200901',3);->200904。
period_diff:該函數(shù)返回兩個(gè)日期間的月數(shù)。如period_diff('200908','200901');->7
PI:返回圓周率。
power:返回參數(shù)1的參數(shù)2次冪。
quarter:該函數(shù)從一個(gè)日期或時(shí)間戳表達(dá)式中返回季度值。結(jié)果的值總是介于1~4之間。不過(guò)和我們?nèi)粘I钪械募径炔煌?~3月為1,4~6月為2,7~9月為3,10~12月為4。
rand:該函數(shù)返回0.0和1.0之間的一個(gè)隨機(jī)數(shù)。參數(shù)表示下一個(gè)隨機(jī)值的計(jì)算起點(diǎn)。使用相同的參數(shù)值重復(fù)調(diào)用該函數(shù),結(jié)果總是相同的。如cast(rand()*1000 as unsigned integer);
repeat:該函數(shù)將參數(shù)1的值重復(fù)參數(shù)2給定的次數(shù)。
replace:該函數(shù)使參數(shù)1指定的字符串中由參數(shù)2指定的值替換為參數(shù)3指定的值。如replace('data','a','e');->'dete'。
reverse:該函數(shù)顛倒一個(gè)字符串值中的字符的順序。
right:該函數(shù)返回參數(shù)1的右側(cè)部分。該部分長(zhǎng)度由第二個(gè)參數(shù)指定。
round:該函數(shù)將一個(gè)數(shù)字的精度舍入到指定的位數(shù)。如round(123.4,-1);->100;round(183.4,-2);->200。
rpad:將參數(shù)3的值填充到參數(shù)1的右側(cè),知道值的總長(zhǎng)度等于參數(shù)2指定的長(zhǎng)度,與lpad相對(duì)。rpad('data',2,'base')->'da'。
second:該函數(shù)返回一個(gè)時(shí)間或時(shí)間戳表達(dá)式中的秒數(shù)。
sec_to_time:該函數(shù)將秒數(shù)變換為時(shí)間。如sec_to_time((24*60*60)-1);->23:59:59
sign:該函數(shù)返回一個(gè)數(shù)值的字符。sign(50);->1;sign(0)->0;sign(-50)->-1;
space:該函數(shù)生成一個(gè)空格行,空格個(gè)數(shù)為參數(shù)指定的值。
sqrt:返回參數(shù)的平方根值。
strcmp:該函數(shù)比較兩個(gè)字符串表達(dá)式的值。如果參數(shù)值相等,那么結(jié)果為0,如果參數(shù)1的值較小,那么返回-1,否則結(jié)果為1。
substring:該函數(shù)從參數(shù)1中減去部分字符串值,參數(shù)2給出起始點(diǎn),參數(shù)3給出子付數(shù)。如substring('database',5,2);->'ba'。
substring_index:該函數(shù)查找參數(shù)2表示的值在參數(shù)1中的第參數(shù)3此出現(xiàn)。如果參數(shù)3為正表示從左側(cè)查找,返回從左側(cè)開(kāi)始找到的該次出現(xiàn)。如果參數(shù)3為負(fù),則從右側(cè)開(kāi)始查找。如substring_index('database','a',3);->'datab';substring_index('database','a',-3);->'tabase';substring_index('database','data',1);->'';substring_index('database','data',-1);->'base'
subtime:該函數(shù)對(duì)兩個(gè)時(shí)間表達(dá)式執(zhí)行相減操作并返回一個(gè)新時(shí)間,timediff與此函數(shù)功能相似。
time:該函數(shù)返回一個(gè)時(shí)間或時(shí)間戳表達(dá)式的時(shí)間部分。如time('12:13');->12:13:00
time_to_sec:該函數(shù)將時(shí)間變換為秒數(shù)。如time_to_sec('00:16:40');->1000
timestampdiff:該函數(shù)計(jì)算兩個(gè)日期或時(shí)間戳表達(dá)式間的時(shí)間。參數(shù)1表示時(shí)間間隔單元,如day,month,year,quarter,week,hour,minute,second,frac_second,參數(shù)2和參數(shù)3形成兩個(gè)表達(dá)式。如timestampdiff(day,'2009-01-01','2009-01-04');->4.
timestamp:該函數(shù)將參數(shù)1變換為一個(gè)時(shí)間戳,如果指定了參數(shù)2,則它應(yīng)該是一個(gè)時(shí)間表達(dá)式,且會(huì)被添加到參數(shù)1的值中。
timestampadd:該函數(shù)將時(shí)間間隔添加到一個(gè)日期或時(shí)間戳表達(dá)式。參數(shù)1表示時(shí)間間隔的單元,參數(shù)2表示天數(shù)或月數(shù)等,參數(shù)3表示時(shí)間間隔添加到的表達(dá)式。如timestampadd(DAY,2,'2009-01-01');->'2009-01-03';timestampadd(MONTH,2,'2009-01-01');->"2009-03-01"。
trim:該函數(shù)刪除參數(shù)1表示的字符串值中開(kāi)始和最后的所有空格。
truncate:該函數(shù)將數(shù)字截?cái)嗟街付ǖ男?shù)位數(shù),注意和round的區(qū)別,round是四舍五入,而truncate是截?cái)唷H鐃runcate(123.45,-1);->120。truncate(123.375,1);->123.3。
unhex:與hex相對(duì),將十六進(jìn)制表示的參數(shù)轉(zhuǎn)換為相應(yīng)的字符。如unhex(hex('hello'))'->hello
ucase:類似upper,都是將參數(shù)中的所有小寫(xiě)字母轉(zhuǎn)換為大寫(xiě)字母。
week:該函數(shù)從一個(gè)日期或時(shí)間戳表達(dá)式中返回周數(shù),類似的函數(shù)還有weekofyear。結(jié)果介于1~53之間的一個(gè)整數(shù)。如week('2009-06-07');->23
weekday:該函數(shù)返回一周中的天數(shù)。結(jié)果為介于0~6之間的數(shù)。0表示星期一。
year:該函數(shù)從一個(gè)日期或時(shí)間戳表達(dá)式中返回年數(shù)。
yearweek:如果指定參數(shù)1,則該函數(shù)從一個(gè)時(shí)間戳或日期表達(dá)式中返回格式為YYYYWW的年份及周數(shù)。周數(shù)的范圍為01~52之間。如yearweek('2009-07-06');->200927