一、簡介
1、前言與初衷
由于最近工作一直用Oracle,故對Oracle數(shù)據(jù)庫研究為對象。 根據(jù)工作業(yè)務(wù)需求實際情況進行功能研發(fā)。為什么要開發(fā)呢?因為在數(shù)據(jù)庫升級或者遷移的時候,為了保證不同環(huán)境不同數(shù)據(jù)庫數(shù)據(jù)保持同步,故數(shù)據(jù)庫SQL腳本非常作用。比如:數(shù)據(jù)庫主腳本,副腳本,增量腳本。
2、目的與作用
1、 快速產(chǎn)出自定義規(guī)則需要的SQL腳本。
2、減少人工編寫SQL腳本出錯率問題,完全通過程序檢測SQL準(zhǔn)確性。
3、幫助開發(fā)人員提高SQL編寫效率,減少人工編寫SQL開發(fā)成本問題。
4、幫助開發(fā)人員節(jié)約時間,同時避免繁瑣不必要編寫SQL的工作。
3、 什么是主腳本、副腳本、增量腳本呢?
1、主腳本指數(shù)據(jù)庫表或存儲過程,視圖腳本,序列等腳本。
2、副腳本指必須執(zhí)行主腳本之后才執(zhí)行的腳本。換句話說在沒執(zhí)行主鍵腳本的情況下,副腳本執(zhí)行之后會回滾事務(wù)失敗。
3、增量腳本指在執(zhí)行主腳本或副腳本之后,根據(jù)需求對某個表添加/修改約束(主外鍵約束,長度約束等),添加/修改字段/添加數(shù)據(jù)等情況對數(shù)據(jù)庫結(jié)構(gòu)改變處理的一種行為腳本。
二、實現(xiàn)方式與原理
2.1實現(xiàn)方式
1、實現(xiàn)方式分:
正向與逆向實現(xiàn)。什么是正向與逆行呢【是否有雞還是有蛋,先后道理同等】
2、正向方式:首先把設(shè)計好數(shù)據(jù)庫表文檔,把所有表的字段屬性配置到EXCEL或者CSV格式的文件通過JXL/POI技術(shù)去讀取文件的字段,再通過其他技術(shù)一系列程序處理之后生成所需要的SQL腳本。
3、逆向方式:首先有數(shù)據(jù)庫表,然后通過ORM持久化技術(shù)連接數(shù)據(jù)庫再讀取表的字段等屬性出來,再通過其他技術(shù)一系列程序處理之后生成所需要的SQL腳本。
2.2原理
對數(shù)據(jù)庫軟件內(nèi)置核心表或視圖查詢出來存儲用戶行為表結(jié)構(gòu)所有屬性信息,對此屬性結(jié)構(gòu)信息進行分析與組裝所需要SQL腳本。
三、技術(shù)選型體系與圖解
- 技術(shù)選型體系與圖解
四、Oracle自帶系統(tǒng)表與常用的SQL語法
- Oracle自帶系統(tǒng)表與常用的SQL語法
五、開發(fā)環(huán)境與工具
-
5.1Nexu中央倉庫
Nexus 是Maven倉庫管理器,如果你使用Maven,可以從Maven中央倉庫下載和上傳所需要的構(gòu)件(artifact)
官方網(wǎng):http://www.sonatype.org/nexus/
推薦學(xué)習(xí)博客:http://blog.csdn.net/wang379275614/article/details/43940259
-
5.2 Eclipse
Eclipse 是一個開放源代碼的、基于Java的可擴展開發(fā)平臺
-
5.3 Tomcat
Tomcat是Apache 軟件基金會(Apache Software Foundation)的Jakarta 項目中的一個核心項目,是一個輕量級的Web服務(wù)器.
官方網(wǎng):http://tomcat.apache.org/
-
5.4 JDK
JDK是 Java 語言的軟件開發(fā)工具包,主要用于移動設(shè)備、嵌入式設(shè)備上的java應(yīng)用程序。JDK是整個java開發(fā)的核心,它包含了JAVA的運行環(huán)境,JAVA工具和JAVA基礎(chǔ)的類庫
官方網(wǎng):http://www.oracle.com/technetwork/java/javase/downloads/index.html
-
5.5Maven
Apache Maven是一個軟件項目管理和理解工具。 基于項目對象模型(POM)的概念,Maven可以從中央信息管理項目的構(gòu)建,報告和文檔。
官方網(wǎng):http://maven.apache.org/
推薦學(xué)習(xí)博客:
https://yq.aliyun.com/articles/28591
http://www.yiibai.com/maven/maven_project_documents.html
-
5.6ER-Ermaster
ERMaster是一個用于設(shè)計ER模型圖的Eclipse插件。提供的功能包括:從數(shù)據(jù)庫導(dǎo)入關(guān)系生成ER圖,導(dǎo)出設(shè)計圖,導(dǎo)出DDL數(shù)據(jù)定義語句等,詳細教程請看
官方網(wǎng):http://ermaster.sourceforge.net/
六、前端的技術(shù)選型
- BootStrap BootStrap,來自 Twitter,是目前很受歡迎的前端框架Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的,它簡潔靈活,使得 Web 開發(fā)更加快捷。官方網(wǎng): http://www.bootcss.com/
Font Awesome 為您提供可縮放的矢量圖標(biāo),您可以使用CSS所提供的所有特性對它們進行更改,包括:大小、顏色、陰影或者其它任何支持的效果。官方網(wǎng):http://fontawesome.dashgame.com/
jQuery 是一個快速、簡潔的JavaScript框架, jQuery設(shè)計的宗旨是“write Less,Do More”,即倡導(dǎo)寫更少的代碼,做更多的事情。官方網(wǎng): http://jquery.com/
SyntaxHighlighter–最優(yōu)秀的JavaScript代碼高亮插件,它是一款完全基于JavaScript的代碼高亮插件SyntaxHighlighter可以對大部分編程語言進行著色渲染,而且代碼高亮的性能也非常不錯??梢宰远x主題文件,在初始化的時候指定自己喜歡的主題即可,官方網(wǎng)站:http://alexgorbatchev.com/SyntaxHighlighter/
Google Code Prettify–自由地JavaScript代碼高亮插件Google Code Prettify是一款由Google推出的JavaScript代碼高亮插件,Google Code Prettify可以對C/C++,Java,Python,Ruby,Perl等編程語言代碼高亮著色。官方網(wǎng)站:http://code.google.com/p/google-code-prettify/
Highlight.js –多風(fēng)格JavaScript代碼高亮插件Highlight.js是一個用于在任何web頁面上高亮著色顯示各種示例源代碼語法的JavaScript項目。
官方網(wǎng)站:https://highlightjs.org/
Prism.JS - 輕量級JavaScript代碼高亮插件Prism.JS是目前最為輕量級的JS代碼高亮插件,他壓縮后只有2KB的大小,Prism.JS也支持大部分流行的編程語言,并且支持多種主題樣式,開發(fā)者只需要引用CSS文件和JS文件即可完成。官方網(wǎng)站:http://prismjs.com/
jQuery.Syntax–jQuery輕量級代碼高亮插件,這款代碼高亮插件是基于jQuery的,同樣也是輕量級的,渲染速度非???官方網(wǎng)站:http://www.codeotaku.com/projects/jquery-syntax/index.en
DlHighlight–jQuery簡單高效代碼高亮插件DlHighlight是基于JavaScript的代碼高亮插件,非常簡單,目前只支持JavaScript, CSS, XML, HTML。
官方網(wǎng)站:http://mihai.bazon.net/projects/javascript-syntax-highlighting-engine
Rainbow.js – 可擴展的JavaScript代碼高亮插件 Rainbow 是JavaScript開發(fā)的語法高亮工具。被設(shè)計為輕量級(壓縮后僅1.4 kb),使用簡單,可擴展。語法高亮主題完全通過CSS定義?;谡齽t表達式實現(xiàn)。
官方網(wǎng)站:http://craig.is/making/rainbows
- LayerUI與jBox彈窗技術(shù)
layer是一款web彈層組件,致力于服務(wù)各個水平段的開發(fā)人員。
官方網(wǎng): http://layer.layui.com/
colResizable拖拽插件,用于調(diào)整手動拖動HML的Table標(biāo)簽列。 它兼容鼠標(biāo)和觸摸設(shè)備,并具有一些不錯的功能,如頁面刷新或回發(fā)后的布局持久性官方網(wǎng):http://www.bacubacu.com/colresizable/
bumpyText插件,一款能讓文字跳舞的jQuery文字插件,鼠標(biāo)劃過文字即可看到效果。兼容主流瀏覽器* https://github.com/alexanderdickson/bumpyText
七、框架與技術(shù)
Servlet3.x Servlet 3.0 作為 Java EE 6 規(guī)范體系中一員,隨著 Java EE 6 規(guī)范一起發(fā)布,基于Servlet2.5之后的規(guī)范的改良,它基于JDK1.7之后。
推薦學(xué)習(xí)博客
https://www.ibm.com/developerworks/cn/java/j-lo-servlet30/
http://jinnianshilongnian.iteye.com/category/255452
SpringMVC 屬于SpringFrameWork的后續(xù)產(chǎn)品,已經(jīng)融合在Spring Web Flow里面。Spring 框架提供了構(gòu)建 Web 應(yīng)用程序的全功能 MVC 模塊。使用 Spring可插入的 MVC 架構(gòu),從而在使用Spring進行WEB開發(fā)時,可以選擇使用Spring的SpringMVC框架或集成其他MVC開發(fā)框架,如Struts1,Stuts2等。而且Spring體系非常龐大,這里不做詳細描述,想繼續(xù)了解和學(xué)習(xí)請到官方網(wǎng)。 Spring官方網(wǎng) http://spring.io
ORM 對象關(guān)系映射(英語:(Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序技術(shù),用于實現(xiàn)面向?qū)ο缶幊陶Z言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換。從效果上說,其實是創(chuàng)建了一個可在編程語言里使用的“虛擬對象數(shù)據(jù)庫”。面向?qū)ο笫菑能浖こ袒驹瓌t(如耦合、聚合、封裝)的基礎(chǔ)上發(fā)展起來的,而關(guān)系數(shù)據(jù)庫則是從數(shù)學(xué)理論發(fā)展而來的,兩套理論存在顯著的區(qū)別。為了解決這個不匹配的現(xiàn)象,對象關(guān)系映射技術(shù)應(yīng)運而生。對象關(guān)系映射(Object-Relational Mapping)提供了概念性的、易于理解的模型化數(shù)
據(jù)的方法。
- ORM方法論基于三個核心原則:
簡單:以最基本的形式建模數(shù)據(jù)。傳達性:數(shù)據(jù)庫結(jié)構(gòu)被任何人都能理解的語言文檔化。精確性:基于數(shù)據(jù)模型創(chuàng)建正確標(biāo)準(zhǔn)化的結(jié)構(gòu)。
典型地,建模者通過收集來自那些熟悉應(yīng)用程序但不熟練的數(shù)據(jù)建模者的人的信息開發(fā)信息模型。建模者必須能夠用非技術(shù)企業(yè)專家可以理解的術(shù)語在概念層次上與數(shù)據(jù)結(jié)構(gòu)進行通訊。建模者也必須能以簡單的單元分析信息,對樣本數(shù)據(jù)進行處理。ORM專門被設(shè)計為改進這種聯(lián)系。
比如:(JDBC,JdbcTemplate,Hibernate ,Ibatis/MyBatis)等
- 本項目框架在3年前工作中用到JdbcTemplate在資料的時候看到oschina大牛的一篇文章,故下決心通過學(xué)習(xí)整理一個SpringMVC工程作為技術(shù)積累。
- POI與JXL
簡述:POI與JXL都是一個處理Excel文檔的技術(shù)。個人認為:從兩者的使用過程中的角度來看,JXL相對POI會輕巧,占空間內(nèi)存少,Jar只有一個,上手快。不過從知識上的支持沒POI友好,實現(xiàn)方式?jīng)]POI強大。畢竟POI是Apache下的工程項目。建議可以根據(jù)自己的情況進行選擇與學(xué)習(xí)。
1、POI官方網(wǎng): http://poi.apache.org/
2、JXL官方網(wǎng): http://jxl.sourceforge.net/
3、入門例子:
https://github.com/jilongliang/excel-doc-pdf
https://github.com/jilongliang/JL_OutExcel
- JSON
fastjson gson jackjson json-lib org.json
JSON工程例子代碼 https://github.com/jilongliang/json
博客文章:http://blog.csdn.net/jilongliang/article/category/2813267
八、項目結(jié)構(gòu)

Java與Python核心代碼實現(xiàn)
- Java代碼
- 數(shù)據(jù)庫讀取
- 代碼生成器實現(xiàn)思路
@Service
@Transactional
@SuppressWarnings("all")
public class TableServiceImpl extends EntityDaoSupport<UserTables> implements TableService {
@Autowired TableDao tableDao;
@Autowired TableColumnsDao tableColumnsDao;
@Autowired UserColCommentsDao userColCommentsDao;
@Autowired UserTabCommentsDao userTabCommentsDao;
@Autowired UserConsColumnsDao userConsColumnsDao;
public List<UserTables> queryTables(SimplePage page, UserTables object) {
return tableDao.queryTables(page,object);
}
public List<UserTables> queryTableByName(String table_name){
return tableDao.queryTableByName(table_name);
}
@Override
public String createTableSQLScript(String tableName) {
String result = "";
//1、判斷是否存在這個表
List<UserTables> findList = queryTableByName( tableName);
//2、組裝execute immediate 'create table ...'
if(findList!=null &&findList.size()>0){
StringBuffer buffer = new StringBuffer();
//3、獲取表的字段名稱,并且獲取約束是否為空(Null or Not null)
List<UserTabColumns> userTabColumnList = tableColumnsDao.getUserTabColumnsByName(tableName);
List<UserTabComments> userTabCommentList = userTabCommentsDao.getUserTabCommentsByName(tableName);
List<UserColComments> userColCommentList = userColCommentsDao.getUserColCommentsByName(tableName);
UserConsColumns userConsColumns = userConsColumnsDao.getUserConsColumnsByName(tableName);
//----組裝表字段列名
int size = userTabColumnList.size()-1;//計算最后一個表列名
buffer.append("--創(chuàng)建"+tableName+"表").append(ENTER);
buffer.append("declare").append(ENTER);
buffer.append(TAB).append("iCnt number := 0;").append(ENTER);
buffer.append("begin ").append(ENTER);
buffer.append(" select count(*) into iCnt from user_tables where lower(table_name) = lower('"+tableName+"');").append(ENTER);
buffer.append(" if iCnt = 0 then ").append(ENTER);
buffer.append(TAB).append("execute immediate 'create table "+tableName+"").append(ENTER);
buffer.append(TAB).append("(").append(ENTER);
for (int i = 0; i < userTabColumnList.size(); i++) {
UserTabColumns userTabColumns = userTabColumnList.get(i);
UserColComments userColComments = userColCommentList.get(i);
String column_name1 = userColComments.getColumn_name();//列名
String column_name2 = userTabColumns.getColumn_name();//列名
String nullable = userTabColumns.getNullable();//是否允許為空
String data_type = userTabColumns.getData_type();//數(shù)據(jù)庫表的字段類型.
BigDecimal data_length = userTabColumns.getData_length();
BigDecimal data_precision = userTabColumns.getData_precision();
BigDecimal data_scale = userTabColumns.getData_scale();
if(ObjectUtil.isNotEmpty(column_name1) && ObjectUtil.isNotEmpty(column_name2) && column_name1.equalsIgnoreCase(column_name2)){
//判斷表字段類型是否為NULL或NOT NULL
if(ObjectUtil.isNotEmpty(nullable) && !"N".equalsIgnoreCase(nullable)){
if(size==i){
if("VARCHAR2".equalsIgnoreCase(data_type) || "NVARCHAR2".equalsIgnoreCase(data_type) ||"CHAR".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_length+")" ).append(ENTER);
}else if("NUMBER".equalsIgnoreCase(data_type)){
if(data_precision!= null && data_scale!=null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+","+data_scale+") ").append(ENTER);
}else if(data_precision!= null && data_scale==null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+",0) ").append(ENTER);
}else{
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(ENTER);
}
}else if(("DATE".equalsIgnoreCase(data_type))||(data_type!=null && data_type.contains("TIMESTAMP")) ){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(ENTER);
}else if("LONG".equalsIgnoreCase(data_type) ||"NCLOB".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(ENTER);
}
}else{
//為空但是有逗號分開
if("VARCHAR2".equalsIgnoreCase(data_type) || "NVARCHAR2".equalsIgnoreCase(data_type) ||"CHAR".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_length+")" ).append(COMMA).append(ENTER);
}else if("NUMBER".equalsIgnoreCase(data_type)){
if(data_precision!= null && data_scale!=null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+","+data_scale+") ").append(COMMA).append(ENTER);
}else if(data_precision!= null && data_scale==null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+",0) ").append(COMMA).append(ENTER);
}else{
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(COMMA).append(ENTER);
}
}else if(("DATE".equalsIgnoreCase(data_type))||(data_type!=null && data_type.contains("TIMESTAMP")) ){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(COMMA).append(ENTER);
}else if("LONG".equalsIgnoreCase(data_type) ||"NCLOB".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(COMMA).append(ENTER);
}
}
}else{
if(size==i){
if("VARCHAR2".equalsIgnoreCase(data_type) || "NVARCHAR2".equalsIgnoreCase(data_type) ||"CHAR".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_length+") not null " ).append(ENTER);
}else if("NUMBER".equalsIgnoreCase(data_type)){
if(data_precision!= null && data_scale!=null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+","+data_scale+") not null").append(ENTER);
}else if(data_precision!= null && data_scale==null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+",0) not null ").append(ENTER);
}else{
buffer.append(TAB+TAB+column_name1+TAB+data_type+"").append(ENTER);
}
}else if(("DATE".equalsIgnoreCase(data_type))||(data_type!=null && data_type.contains("TIMESTAMP")) ){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(ENTER);
}else if("LONG".equalsIgnoreCase(data_type) ||"NCLOB".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(ENTER);
}
}else{
if("VARCHAR2".equalsIgnoreCase(data_type) || "NVARCHAR2".equalsIgnoreCase(data_type) ||"CHAR".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_length+") not null " ).append(COMMA).append(ENTER);
}else if("NUMBER".equalsIgnoreCase(data_type)){
if(data_precision!= null && data_scale!=null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+","+data_scale+") not null").append(COMMA).append(ENTER);
}else if(data_precision!= null && data_scale==null){
buffer.append(TAB+TAB+column_name1+TAB+data_type+"("+data_precision+",0) not null ").append(COMMA).append(ENTER);
}else{
buffer.append(TAB+TAB+column_name1+TAB+data_type+" ").append(COMMA).append(ENTER);
}
}else if(("DATE".equalsIgnoreCase(data_type))||(data_type!=null && data_type.contains("TIMESTAMP")) ){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(COMMA).append(ENTER);
}else if("LONG".equalsIgnoreCase(data_type) ||"NCLOB".equalsIgnoreCase(data_type)){
buffer.append(TAB+TAB+column_name1+TAB+data_type).append(COMMA).append(ENTER);
}
}
}
}
}
buffer.append(TAB).append(")';").append(ENTER);
//4、獲取表名給予表加備注.(有就加,無默認表描述)
if(ObjectUtil.isNotEmpty(userTabCommentList) && ObjectUtil.isNotEmpty(userTabCommentList.get(0))){
String comments = userTabCommentList.get(0).getComments();
comments = (comments==null?" this is "+tableName+" tableName ":comments);
buffer.append(TAB).append("execute immediate 'comment on table "+tableName +" is ''"+comments+"'''").append(";").append(ENTER);
}
//5、添加主鍵執(zhí)行SQL腳本
if(ObjectUtil.isNotEmpty(userConsColumns) && ObjectUtil.isNotEmpty(userConsColumns.getConstraint_name())){
buffer.append(TAB).append("execute immediate 'alter table "+tableName).append(" add constraint "+userConsColumns.getConstraint_name()+" ");
buffer.append("primary key ("+userConsColumns.getColumn_name()+")' ;").append(ENTER);
}
//6、獲取表字段名給予字段加備注(有就加,無默認字段描述)
for(UserColComments col: userColCommentList){
String comments = col.getComments();
String column_name = col.getColumn_name();
comments = (comments==null?" this is "+column_name+" columnName ":comments);
buffer.append(TAB).append("execute immediate 'comment on column "+tableName+"."+col.getColumn_name()+" is ''"+comments+"'''").append(";").append(ENTER);
}
//---end if
buffer.append(" end if;").append(ENTER);
buffer.append("end;").append(ENTER);
buffer.append("/").append(ENTER);
result = buffer.toString();
}
return result;
}
@Override
public String dropTableSQLScript(String table_name) {
List<UserTables> list = queryTableByName(table_name);
StringBuffer buffer = new StringBuffer();
if(list!=null && list.size()>0){
UserTables sequences = list.get(0);
buffer.append("--"+table_name).append(ENTER);
buffer.append("declare").append(ENTER);
buffer.append(TAB+TAB).append("iCnt number := 0;").append(ENTER);
buffer.append(TAB).append("begin").append(ENTER);
buffer.append(TAB).append(" select count(*) into iCnt from user_tables where lower(table_name) = '"+table_name+"'; --根據(jù)表進行查詢").append(ENTER);
buffer.append(TAB).append(" if iCnt > 0 then ").append(ENTER);
buffer.append(TAB).append(" execute immediate 'drop table "+table_name+"'; --刪除表,表結(jié)構(gòu)和數(shù)據(jù)一起清空 ").append(ENTER);
buffer.append(TAB).append(" end if;").append(ENTER);
buffer.append(TAB).append("end;").append(ENTER);
buffer.append("/").append(ENTER);
return buffer.toString();
}
return null;
}
}
- Python3代碼的實現(xiàn)
- 文件讀取
# -*- coding:utf-8 -*- 處理亂碼
import xlrd
#import xlwt
'''
@Author jilongliang
@Date 2017-04-12
@Copyright (c) All Right Reserved jilong, 2017.
@Description
xlwt和xlwt安裝步驟,請參考博客 http://www.cnblogs.com/sincoolvip/p/5967010.html
http://www.cnblogs.com/lhj588/archive/2012/01/06/2314181.html
'''
#===============全局變量====================
TAB = " "; #空格置位常量
COMMA = ","; #SQL逗號常量
ENTER = "\n"; #換行常量
#===================================
#--------------定義一個讀取excel的方法---------
def read_excel():
resultSQL = "";#返回SQL
#打開文件,Python中以r或R開頭的的字符串表示(非轉(zhuǎn)義的)原始字符串.說明字符串r"XXX"中的XXX是普通字符。
workbook = xlrd.open_workbook(r'D:\table_all.xls')
#獲取所有sheet
sheet_names = workbook.sheet_names() # [u'sheet1', u'sheet2']
#遍歷讀取excel的每個sheet
#for sheet_name in sheet_names:
#print(sheet_name)
#遍歷讀取excel的每個sheet并且讀取有多少個sheet的tab
for sheet_i in range(len(sheet_names)):
sheetName =sheet_names[sheet_i];#sheetName就是表名,在創(chuàng)建excel的時候規(guī)定好即可
sheet = workbook.sheet_by_index(sheet_i) #獲取excel里面有哪些sheet
nrows = sheet.nrows #讀取每個sheet有多少行(sheet里面一個table表格有多少行)
sqlStr = "--創(chuàng)建"+sheetName+"表SQL腳本"+ENTER;#表描述
sqlStr += "declare"+ENTER;#declare關(guān)鍵字
sqlStr += TAB+"iCnt number := 0; "+ENTER;#查詢是否存在此表的記錄數(shù)變量
sqlStr +="begin "+ENTER;#begin關(guān)鍵字
sqlStr +=TAB+"select count(*) into iCnt from user_tables where lower(table_name) = lower('"+sheetName+"'); "+ENTER;
sqlStr +=TAB+"if iCnt = 0 then -- 如果查詢不到這個表就創(chuàng)建這個表"+ENTER;
sqlStr +=TAB+"execute immediate 'create table "+sheetName+" "+ENTER;#組裝創(chuàng)建表SQL腳本
sqlStr +=TAB+"("+ENTER;
#遍歷每個sheet里面的table有多少行
for row_i in range(nrows):
if row_i==2:
#cell(row_i,1)表示從shee的表格的第三行獲取第二個列單元信息
fieldName = sheet.cell(row_i,1).value;#獲取字段名稱
fieldType = sheet.cell(row_i,2).value;#獲取字段類型
fieldLength = sheet.cell(row_i, 3).value;#獲取字段長度
isNull = sheet.cell(row_i, 4).value;#獲取字段是否為空
if fieldLength!='':
fieldLength = '%s' %int(fieldLength) #把數(shù)字轉(zhuǎn)換成String類型
else:
fieldLength = fieldLength
fieldLength = '%s' %fieldLength #把數(shù)字轉(zhuǎn)換成String類型
fieldType = fieldType.upper();#轉(zhuǎn)換成大寫
#判斷是否為Y/N
if isNull!='' and isNull== 'N':#判斷字段為N
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+COMMA+ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+COMMA+ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")!=-1):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
else: #判斷字段為Y
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") " +COMMA + ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+")" +COMMA + ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")>-1 ):
sqlStr += TAB+TAB+fieldName+TAB+fieldType + COMMA + ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
elif row_i>2:
fieldName = sheet.cell(row_i,1).value;#獲取字段名稱
fieldType = sheet.cell(row_i,2).value;#獲取字段類型
fieldLength = sheet.cell(row_i, 3).value;#獲取字段長度
isNull = sheet.cell(row_i, 4).value;#獲取字段是否為空
if fieldLength!='':
#從excel讀取出來的數(shù)字是有小數(shù)點,先轉(zhuǎn)換成整型,由于Python在拼接String的時候,int或double當(dāng)數(shù)字相加了,故要轉(zhuǎn)換成String進行拼接
#為了學(xué)習(xí)階段目前這里使用spit分割出來,加強進一步學(xué)習(xí),double和int是沒有split方法
newFieldLength = '%s'%fieldLength;#double和int是沒有split方法所以轉(zhuǎn)換成一個string類型
if newFieldLength.find(".")>-1: #找到.之后進行處理獲取第0個數(shù)字進行處理轉(zhuǎn)換
fieldLengths = newFieldLength.split(".");#split進行分割
fieldLength = fieldLengths[0];#獲取第0個數(shù)字
fieldLength = '%s' %int(fieldLength) #把數(shù)字轉(zhuǎn)換成String類型
else:
fieldLength = fieldLength #處理為空的數(shù)字長度
fieldLength = '%s' %fieldLength #把數(shù)字轉(zhuǎn)換成String類型
fieldType = fieldType.upper();#轉(zhuǎn)換成大寫
#判斷是否為Y/N
if isNull!='' and isNull== 'N':#判斷字段為N
#計算是否最后一個字段
if nrows-1 ==row_i :
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+ ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+ ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")!=-1):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+ENTER;
else :
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+COMMA+ ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") NOT NULL "+COMMA+ ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")!=-1):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
else : #判斷字段為Y
#計算是否最后一個字段
if nrows-1 ==row_i :
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") "+ ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") "+ ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")!=-1):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+ENTER;
else :
if("VARCHAR2"==fieldType or "NVARCHAR2"==fieldType or "CHAR"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") "+COMMA+ ENTER;
elif("NUMBER"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+"("+fieldLength+") "+COMMA+ ENTER;
elif("DATE"==fieldType or fieldType.find("TIMESTAMP")!=-1):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
elif("LONG"==fieldType or "NCLOB"==fieldType):
sqlStr += TAB+TAB+fieldName+TAB+fieldType+COMMA+ENTER;
#---nrows for循環(huán)結(jié)束
sqlStr += TAB+")'; "+ENTER;#創(chuàng)建表腳本結(jié)束
comentSQL = addTableAndColumnComent(sheet, nrows); #對表與字段進行添加備注描述
sqlStr += comentSQL;
sqlStr += TAB+"end if; "+ENTER;#if腳本結(jié)束
sqlStr += "end; "+ENTER#sql腳本結(jié)束
sqlStr += "/"+ENTER;#sql腳本結(jié)束
#sqlStr=sqlStr.encode('utf8')
resultSQL += sqlStr; #累計SQL
#------sheet_names for循環(huán)結(jié)束
print(resultSQL);#打印結(jié)果
#--------------添加表名與列的注釋方法---------
def addTableAndColumnComent(sheet,nrows):
resultSQL ="";
for row_i in range(nrows):
if(row_i==0):
tableName = sheet.cell(row_i,1).value;#獲取表名稱
tableNameDesc = sheet.cell(row_i,2).value;#獲取表描述
if tableNameDesc=='' :
tableNameDesc = " this is "+tableName+" tableName "
else :
tableNameDesc = tableNameDesc
elif (row_i==2):
isPrimaryKey = sheet.cell(row_i,0).value;#獲取表主鍵
tableName = sheet.cell(0,1).value;#獲取表名稱
fieldName = sheet.cell(row_i,1).value;#獲取字段
if isPrimaryKey!='' :
resultSQL += TAB+"execute immediate 'alter table "+tableName+" add constraint PK_"+fieldName+" ";
resultSQL += " primary key ("+fieldName+")' ;"+ENTER;
elif(row_i>2):
tableName = sheet.cell(0,1).value;#獲取表名稱
fieldName = sheet.cell(row_i,1).value;#獲取字段
fieldDescription = sheet.cell(row_i,6).value;#獲取字段描述
if fieldName!='':
resultSQL += TAB+"execute immediate 'comment on column "+tableName+"."+fieldName+" is ''"+fieldDescription+"'''"+";"+ENTER;
#----for end
return resultSQL;
#在很多python腳本中在最后的部分會執(zhí)行一個判斷語句if __name__ == "__main__:",之后還可能會有一些執(zhí)行語句。那添加這個判斷的目的何在?
#在python編譯器讀取源文件的時候會執(zhí)行它找到的所有代碼,而在執(zhí)行之前會根據(jù)當(dāng)前運行的模塊是否為主程序而定義變量__name__的值為__main__還是模塊名。
#因此,該判斷語句為真的時候,說明當(dāng)前運行的腳本為主程序,而非主程序所引用的一個模塊。這在當(dāng)你想要運行一些只有在將模塊當(dāng)做程序運行時而非當(dāng)做模塊引用時才執(zhí)行
#的命令,只要將它們放到if __name__ == "__main__:"判斷語句之后就可以了
if __name__ == '__main__':
read_excel()
十、運行結(jié)果
-
前端結(jié)果1
前端結(jié)果2 - 前端結(jié)果3
- 文檔結(jié)構(gòu)
十一、總結(jié)
- 此文章在兩年前就已經(jīng)開發(fā)和發(fā)布到網(wǎng)上博客理論,由于以前寫得過于長,對此文章部分刪減,文章并且全文用到MD語法進行梳理,由于從閱讀性進行改善.。
如果有興趣的朋友們可以看我CSDN
) 或是ITEYE 歡迎轉(zhuǎn)載或收藏或指出不好之處,共同學(xué)習(xí)和交流,人的成長需要更好的養(yǎng)料的灌溉}謝謝!








