核心内容摘要
孙尚香正能量坐钢筋
我写这篇ä¸�是“产å“�介ç»�â€�而是一份替æ�¢é¡¹ç›®çš„å¼€å�‘者笔记哪些地方能çœ�心哪些地方最好æ��å‰�踩刹车。文里所有 SQL/PLSQL 片段我都按“å¤�制到 ksql 就能跑â€�æ�¥å‡†å¤‡æŠŠ Oracle è¿�移里最常è§�çš„ä¸€äº›æ”¹é€ ç‚¹å°½é‡�用一æ�¡èƒ½æ‰§è¡Œçš„路线串起æ�¥ã€‚æ–‡ç« ç›®å½•
为什么我会把“替��拆�四件事
ä¸€å¼ å›¾è¯´æ¸…è¿�ç§»æµ�æ°´çº¿æˆ‘ä¹ æƒ¯è¿™ä¹ˆè�½åœ°
ç�¯å¢ƒä¸�å‰�ç½®Windows 上用 ksql 快速æ�一个“å�¯è·‘通â€�çš„å®�验场
1 ���“Oracle 模�自检�
æ•°æ�®ç±»å�‹æ˜ 射我最关心的ä¸�是“能ä¸�能建表â€�而是“è¯ä¹‰æœ‰æ²¡æœ‰æ‚„æ‚„å�˜â€�
��用一个“订�系统�把表�索引�分区��列跑通
1 一键�始化��制粘贴执行
Oracle 特有功能的替代å®�ç�°æˆ‘最常写的三类改é€
1 ROWNUM能用但è¦�å°�心“先æ�’åº�还是先截æ–â€�
2 CONNECT BY层次查询能��建议把递归逻辑测试到边界
3 DBLINKè·¨åº“è®¿é—®èƒ½ç”¨ä½†æˆ‘å»ºè®®å…ˆå®šæ¸…â€œä½ è¦�的是查询还是å�Œæ¥â€�
å˜å‚¨è¿‡ç¨‹ã€�函数ã€�æ¸¸æ ‡æˆ‘æ›´å–œæ¬¢â€œå…ˆå°�æ¥è·‘通å†�规模化è¿�ç§»â€�
1 一个�跑通的过程计算订�金� 记录审计自治事务
2 æ¸¸æ ‡è¿�移显å¼�æ¸¸æ ‡ %ROWCOUNT 的常è§�模å¼�
性能调优我对比的��是“快�快�而是“�么定��
1 用执行计划把“猜测���“���
2 用 HINT �“��对比�别拿它当长期��
3 分区ä¸�统计信æ�¯å…ˆæŠŠâ€œèƒ½å‘½ä¸â€�å�šå¯¹æˆ‘在è¿�ç§»å¤�盘里最常写的“踩å�‘清å�•â€�
为什么我会把“替æ�¢â€�拆æˆ�四件事把 Oracle æ�¢æˆ�金仓KingbaseES大家第一å��应往往是“兼容性到底行ä¸�行â€�。但真到项目里最è¦�命的ä¸�是“能ä¸�能跑â€�而是“æ€�么稳稳交付â€�ã€‚è¯´ç™½äº†å…¼å®¹æ€§å¸®ä½ å°‘æ”¹ä»£ç �ä¸�ä¼šæ›¿ä½ æŠŠé¡¹ç›®å�šå®Œã€‚æ‰€ä»¥æˆ‘ä¹ æƒ¯å…ˆæŠŠæ›¿æ�¢æ‹†æˆ�å››ä»¶äº‹è¯æ³•ä¸�对象SQLã€�视图ã€�åº�列ã€�触å�‘器ã€�包/过程/函数是å�¦èƒ½æ�¥ä½�æ•°æ�®ç±»å�‹NUMBER/DATE/CLOB 这类“è€�朋å�‹â€�到底æ€�么è�½åœ°ç²¾åº¦å’Œè¯ä¹‰æ˜¯å�¦ä¸€è‡´è¿�行ä¸�工具链脚本æ€�么跑ã€�æ€�么å›�å½’ã€�æ€�么定ä½�æ…¢ SQL上线é£�险å›�滚ç–ç•¥ã€�ç�°åº¦ã€�å�Œå†™/对账窗å�£æ€�么设计。手册里对 Oracle 兼容覆盖é�¢å†™å¾—很细在 Oracle 模å¼�下数æ�®ç±»å�‹ã€�伪列ã€�DML/DQLã€�过程化è¯è¨€ã€�触å�‘器ã€�动æ€� SQL 这些常è§�能力都在兼容范围里è¿� DBLink è¿™ç§�å��“工程å�‘â€�çš„èƒ½åŠ›ä¹Ÿç»™åˆ°äº†ã€‚è¿™ç¯‡æ–‡ç« æˆ‘å°±æŒ‰â€œç�°åœºçœŸçš„会踩â€�的路å�æ�¥å†™å…ˆæŠŠæ•°æ�®ç±»å�‹è�½ç¨³å†�把过程/函数跑通最å��把 ROWNUMã€�CONNECT BYã€�DBLINK 这些高频点用å�¯æ‰§è¡Œçš„æ–¹å¼�验è¯�一é��。
ä¸€å¼ å›¾è¯´æ¸…è¿�ç§»æµ�æ°´çº¿æˆ‘ä¹ æƒ¯è¿™ä¹ˆè�½åœ°æº�库盘点对象/SQL/æ•°æ�®é‡�/ä¾�赖问题è¯�归类类å�‹/è¯æ³•/过程/è¿�ç»´ç›®æ ‡åº“å‡†å¤‡Oracle模å¼�å®�例å�‚数基线结æ�„è¿�ç§»schema/表/索引/分区/åº�列数æ�®è¿�移全é‡�-æ ¡éªŒ-å¢�é‡�窗å�£SQL改写ä¸�兼容验è¯�ROWNUM/CONNECT BY/外è¿�æ�¥/包性能å›�归执行计划/索引/统计信æ�¯ä¸Šçº¿ä¸�å›�滚预案ç�°åº¦/å�Œå†™/对账我ä¸�太建议一上æ�¥å°±â€œå…¨é‡�自动è¿�â€�。更稳的å�šæ³•æ˜¯å…ˆæŠŠé£�险收敛挑一个模å�—æˆ–ä¸€ç»„æ ¸å¿ƒè¡¨æŠŠç±»å�‹ã€�过程ã€�æ…¢ SQL 这三件事跑通手里有了å�¯å¤�用的套路å†�扩é�¢ã€‚
ç�¯å¢ƒä¸�å‰�ç½®Windows 上用 ksql 快速æ�一个“å�¯è·‘通â€�çš„å®�éªŒåœºä½ è¯´ä½ çš„ç�¯å¢ƒæ˜¯ Windows 且在 ksql 上æ“�作下é�¢æ‰€æœ‰æ¼”示默认满足Windows 已安装 KingbaseES并创建了 Oracle 模å¼�å®�ä¾‹ä½ èƒ½åœ¨ PowerShell / Windows Terminal 䏿‰§è¡Œksql如æ�œä½ çš„ç�¯å¢ƒè¿™ä¸€æ¥å°±å�¡ä½�了比如端å�£ä¸�通ã€�æœ�务没起æ�¥ã€�ksql è¿�ä¸�上我之å‰�写过一篇ä»�安装到è¿�通性验è¯�的笔记按æ¥éª¤èµ°åŸºæœ¬ä¸�会翻车Windows 安装 KingbaseES V9R1C10 ä¸� Oracle 兼容特性å®�战概念解释我就ä¸�展开了先用能跑通的方å¼�把ç�¯å¢ƒç¡®è®¤ä¸‹æ�¥å�ªè¦�ä½ åœ¨ ksql é‡ŒæŠŠå‡ ä¸ªå…³é”®è¯æ³•è·‘èµ·æ�¥å��é�¢æ‰€æœ‰å®�æ“�æ‰�有æ„�义。
1 ���“Oracle 模�自检�ksql -h
127.
0.
1 -p54321-U system -dtest端å�£è¿™å�—æŒ‰ä½ çš„å®�例æ�¥æˆ‘这边 Oracle 兼容版用的是 54322所以截图里会看到 54322。进到test#之å��å…ˆå�šä¸‰ä»¶äº‹SELECTCURRENT_USER;SELECTCURRENT_TIMESTAMP;-- Oracle ä¹ æƒ¯çš„ dual 伪表能跑通基本说æ˜�ä½ åœ¨ Oracle è¯ä¹‰ç�¯å¢ƒé‡ŒSELECTCURRENT_DATEFROMdual;如æ�œä½ æ�¥ä¸‹æ�¥è¿˜èƒ½è·‘通ROWNUMå’ŒCONNECT BY基本å�¯ä»¥è®¤ä¸ºâ€œOracle è¿�ç§»çš„é«˜é¢‘è¯æ³•â€�处在å�¯éªŒè¯�范围内第 6 ç« ä¼šç»™ä¾‹å�。
æ•°æ�®ç±»å�‹æ˜ 射我最关心的ä¸�是“能ä¸�能建表â€�而是“è¯ä¹‰æœ‰æ²¡æœ‰æ‚„æ‚„å�˜â€�ç±»å�‹æ˜ 射这事最容易被“建表ä¸�报错â€�给骗了。表是建起æ�¥äº†æ²¡é”™ä½†è¯ä¹‰ä¸€æ—¦å��了å��é�¢å°±æ˜¯æ…¢æ…¢å¯¹è´¦ã€�慢慢æ�‰å�‘。真å®�项目里类å�‹é£�é™©æˆ‘åŸºæœ¬éƒ½æ ½åœ¨è¿™ä¸‰ç±»ä¸Šç²¾åº¦NUMBER(p,s) 的范围ã€�金é¢�å—æ®µçš„å››èˆ�五入时间è¯ä¹‰DATE 到底带ä¸�带时间应用是å�¦ä¾�èµ–éš�å�«æ—¶é—´å¤§å¯¹è±¡ä¸�å—符集CLOB/NCLOBã€�VARCHAR2/NVARCHAR2 的边界值ä¸�ç¼–ç �。KingbaseES 的手册里有类å�‹å¯¹ç…§è¡¨æ¯”如 numeric/number 对 Oracle NUMBER çš„å¯¹åº”å…³ç³»ç‰æˆ‘自己在项目里常用的“è�½åœ°æ˜ 射建议â€�å¤§æ¦‚æ˜¯è¿™æ ·Oracle 常è§�ç±»å�‹è¿�ç§»è�½åœ°å»ºè®®KingbaseES Oracle 模å¼�我会é¢�外检查的点NUMBER(p,s)优先ä¿�æŒ�为 NUMBER(p,s) / NUMERIC(p,s)金é¢�å—æ®µæ˜¯å�¦å˜åœ¨éš�å�«ç²¾åº¦æ‰©å±•VARCHAR2(n)VARCHAR(n)å—æ®µé•¿åº¦è¾¹ç•Œã€�是å�¦ä¾�赖空串/空值差异CHAR(n)CHAR(n)å°¾éƒ¨ç©ºæ ¼æ¯”è¾ƒè§„åˆ™DATEDATEOracle è¯ä¹‰ç�¯å¢ƒä¸‹æ›´è´´è¿‘å�Ÿç”¨æ³•是å�¦æœ‰â€œå�ªå˜æ—¥æœŸä¸�å˜æ—¶é—´â€�的约定TIMESTAMPTIMESTAMP时区列是å�¦éœ€è¦� TIMESTAMP WITH TIME ZONECLOB/NCLOBCLOB/NCLOB大嗿®µæ›´æ–°æ˜¯å�¦èµ° DBMS_LOB 路线BLOBBLOB事务ä¸�定ä½�器用法我自己的ç»�验是别在è¿�移第一天就“顺手把 NUMBER 全改æˆ� INTâ€�ã€‚ä½ çœ�下æ�¥çš„那点å˜å‚¨ç©ºé—´å��é�¢å¾ˆå®¹æ˜“以“线上对账差
01â€�的形å¼�åŠ å€�è¿˜ä½ ã€‚
å®�æ“�用一个“订å�•系统â€�把表ã€�索引ã€�分区ã€�åº�列跑通下é�¢è¿™å¥—脚本å�¯ä»¥ç›´æ�¥åœ¨ ksql 里执行建表ã€�建索引ã€�建åº�列ã€�建分区表ã€�æ�’æ•°æ�®ã€‚一å�£æ°”跑完å��é�¢ç¬¬ 6ã€�7ã€�8 ç« çš„å…¼å®¹éªŒè¯�和性能定ä½�就能顺ç�€å�šä¸‹å�»ã€‚
1 一键åˆ�始化å�¯å¤�制粘贴执行-- 清ç�†å¦‚å˜åœ¨DROPTABLEIFEXISTSt_order_item;DROPTABLEIFEXISTSt_order;DROPTABLEIFEXISTSt_order_audit;DROPSEQUENCEIFEXISTSseq_order_id;-- åº�列Oracle项目里常è§�主键æ�¥è‡ª sequenceCREATESEQUENCE seq_order_idSTARTWITH100001INCREMENTBY1;-- 订å�•主表按下å�•æ—¶é—´å�šèŒƒå›´åˆ†åŒºç¤ºä¾‹æŒ‰æœˆCREATETABLEt_order(order_id NUMBER(12,
NOTNULL,customer_id NUMBER(12,
NOTNULL,order_timeTIMESTAMPNOTNULL,statusVARCHAR(
NOTNULL,remarkVARCHAR(
,total_amount NUMBER(12,
DEFAULT0NOTNULL,CONSTRAINTpk_t_orderPRIMARYKEY(order_id))PARTITIONBYRANGE(order_time)(PARTITIONp202601VALUESLESS THAN(TO_DATE(
,YYYY-MM-DD)),PARTITIONp202602VALUESLESS THAN(TO_DATE(
,YYYY-MM-DD)));-- �细表CREATETABLEt_order_item(item_id NUMBER(12,
NOTNULL,order_id NUMBER(12,
NOTNULL,skuVARCHAR(
NOTNULL,qty NUMBER(12,
NOTNULL,unit_price NUMBER(12,
NOTNULL,CONSTRAINTpk_t_order_itemPRIMARYKEY(item_id));CREATEINDEXidx_t_order_item_order_idONt_order_item(order_id);CREATEINDEXidx_t_order_customer_timeONt_order(customer_id,order_time);-- 审计表演示自治事务/日志CREATETABLEt_order_audit(audit_id NUMBER(12,
NOTNULL,order_id NUMBER(12,
,actionVARCHAR(
NOTNULL,action_timeTIMESTAMPDEFAULTCURRENT_TIMESTAMPNOTNULL,detailVARCHAR(
,CONSTRAINTpk_t_order_auditPRIMARYKEY(audit_id));CREATESEQUENCE seq_audit_idSTARTWITH1INCREMENTBY1;-- �入一些订�INSERTINTOt_order(order_id,customer_id,order_time,status,remark,total_amount)VALUES(seq_order_id.NEXTVAL,2001,TO_TIMESTAMP(
10:12:00,YYYY-MM-DD HH24:MI:SS),NEW,NULL,
;INSERTINTOt_order(order_id,customer_id,order_time,status,remark,total_amount)VALUES(seq_order_id.NEXTVAL,2002,TO_TIMESTAMP(
09:45:10,YYYY-MM-DD HH24:MI:SS),PAID,年度��首�,
;-- æ�’å…¥æ˜�ç»†æ‰‹å·¥å†™å‡ æ�¡å��é�¢ä¹Ÿä¼šæ¼”示用 CONNECT BY 批é‡�é€ æ•°INSERTINTOt_order_item(item_id,order_id,sku,qty,unit_price)SELECT1,(SELECTMIN(order_id)FROMt_order),SKU-001,2,
9
50FROMdual;INSERTINTOt_order_item(item_id,order_id,sku,qty,unit_price)SELECT2,(SELECTMIN(order_id)FROMt_order),SKU-002,1,
1
00FROMdual;INSERTINTOt_order_item(item_id,order_id,sku,qty,unit_price)SELECT3,(SELECTMAX(order_id)FROMt_order),SKU-003,3,
3
90FROMdual;COMMIT;验�一下对象是�都在SELECTCOUNT(*)ASorder_cntFROMt_order;SELECTCOUNT(*)ASitem_cntFROMt_order_item;
Oracle 特有功能的替代å®�ç�°æˆ‘最常写的三类改é€
1 ROWNUM能用但è¦�å°�心“先æ�’åº�还是先截æ–â€�ROWNUM 伪列是为了兼容 Oracle è€ŒåŠ çš„æ‰‹å†Œé‡Œä¹Ÿä¸“é—¨æ��醒了一个ç»�å…¸å�‘带 ORDER BY 的时候ROWNUM 的结æ�œä¼šå�—å�–数顺åº�å½±å“�在项目里我一般这么写 Top-N-- å…ˆæ�’åº�å†�截æ–SELECT*FROM(SELECTorder_id,customer_id,order_time,total_amountFROMt_orderORDERBYorder_timeDESC)WHEREROWNUM10;如æ�œä½ æ›´å��æ ‡å‡†å†™æ³•ä¹Ÿå�¯ä»¥ç›´æ�¥ç”¨ORDER BY ... LIMIT ...。但在è¿�移阶段我通常先求“è€� SQL 能稳定跑â€�ç‰æ ¸å¿ƒé“¾è·¯ç¨³äº†å†�æ…¢æ…¢æŠŠå†™æ³•å¾€æ›´æ ‡å‡†çš„æ–¹å�‘收敛。
2 CONNECT BY层次查询能æ�¥ä½�建议把递归逻辑测试到边界层次查询这å�—我更关心的是“能ä¸�能把è€�逻辑å�Ÿæ ·æ�¥ä½�â€�。手册里也写得比较æ˜�确层次查询用äº�父å�关系数æ�®çš„层次返å›�KingbaseES ä¸� Oracle 都支æŒ�è¯ä¹‰ä¸Šæ˜¯å…¼å®¹çš„下é�¢ç”¨ä¸€ä¸ªç»„织结æ�„å�šæ¼”ç¤ºå�Œæ—¶æŠŠâ€œé€ 测试数æ�®â€�的方法也带上DROPTABLEIFEXISTSt_dept;CREATETABLEt_dept(dept_id NUMBER(12,
PRIMARYKEY,parent_id NUMBER(12,
,dept_nameVARCHAR(
NOTNULL);INSERTINTOt_deptVALUES(1,NULL,总部);INSERTINTOt_deptVALUES(2,1,ç ”å�‘ä¸å¿ƒ);INSERTINTOt_deptVALUES(3,1,销售ä¸å¿ƒ);INSERTINTOt_deptVALUES(4,2,å¹³å�°ç»„);INSERTINTOt_deptVALUES(5,2,应用组);COMMIT;-- 层次查询ä»�总部开始展开SELECTLPAD( ,(LEVEL-
*
||dept_nameASdept_tree,dept_id,parent_id,LEVELFROMt_deptSTARTWITHdept_id1CONNECTBYPRIOR dept_idparent_idORDERSIBLINGSBYdept_id;è¿�ç§»é¡¹ç›®é‡Œæˆ‘ä¼šä¸“é—¨åŠ ä¸¤ç±»ç”¨ä¾‹æ��å‰�把éš�æ‚£æ�ªå‡ºæ�¥å¾ªç�¯å¼•用parent_id 指å›�自己/祖先能å�¦è¢«å�Šæ—¶å�‘ç�°å±‚级很深100时性能ä¸�æ�’åº�是å�¦ç¬¦å�ˆé¢„期。
3 DBLINKè·¨åº“è®¿é—®èƒ½ç”¨ä½†æˆ‘å»ºè®®å…ˆå®šæ¸…â€œä½ è¦�的是查询还是å�Œæ¥â€�在 Oracle 模å¼�下KingbaseES 的兼容能力ä¸åŒ…å�« DBLink è¿™ç±»é«˜çº§èƒ½åŠ›å®˜ç½‘æ–‡ç« é‡Œä¹Ÿç»™äº† DBLink 在 Oracle 兼容模å¼�下å®�ç�°è·¨åº“å®�时访问/å�Œæ¥çš„æ€�路我在项目里会先问一å�¥ä½ è¦�的是“跨库查询â€�还是“跨库å�Œæ¥â€�。这会影å“�ä½ æ˜¯æŠŠå®ƒå½“ä½œè¿�行时ä¾�赖还是把它当作数æ�®é›†æˆ�链路的一ç�¯ã€‚下é�¢ç»™ä¸€ä¸ªâ€œèƒ½è¯»æ‡‚也好改â€�的例å�远端è¿�æ�¥ä¿¡æ�¯æŒ‰ä½ ç�¯å¢ƒæ›¿æ�¢-- 示例创建数æ�®åº“链æ�¥è¯æ³•é£�æ ¼ä¸� Oracle æ�¥è¿‘-- 具体å�‚æ•°ä¸�æ�ƒé™�è¦�æ±‚ä»¥ä½ ç‰ˆæœ¬çš„æ‰‹å†Œ/规范为准CREATEDATABASELINK lk_remote_financeCONNECTTOremote_user IDENTIFIEDBYremote_passwordUSING
192.
168.
1