spring 生成Excel和PDF文件

          HTML頁面并不總是向用戶顯示數據輸出的最好方式,有時候需要生成不可改變的文件打印,PDF可能是種不錯的選擇。

          Spring支持從數據動態生成PDF或Excel文件

          下面這個簡單實現的例子實現了spring輸出PDF和Excel文件,為了使用Excel電子表格,你需要在你的classpath中加入poi-2.5.1.jar庫文件,而對PDF文件,則需要iText.jar文件。它們都包含在Spring的主發布包中。

          下面是測試項目代碼:


          1、控制器配置代碼
          <?xml?version="1.0"?encoding="UTF-8"?>
          <!DOCTYPE?beans?PUBLIC?"-//SPRING//DTD?BEAN//EN"?"http://www.springframework.org/dtd/spring-beans.dtd">

          <beans>
          ????
          <bean?id="beanNameViewResolver"
          ????????class
          ="org.springframework.web.servlet.view.BeanNameViewResolver"?/>

          ????
          <bean?id="viewController"?class="com.zhupan.spring.ViewController"?/>
          ????
          <bean?id="urlMapping"
          ????????class
          ="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
          ????????
          <property?name="mappings">
          ????????????
          <props>
          ????????????????
          <prop?key="/view*.shtml">viewController</prop>
          ????????????
          </props>
          ????????
          </property>
          ????
          </bean>
          </beans>

          ?3、用于Excel視圖的視圖子類化
          為了在生成輸出文檔的過程中實現定制的行為,我們將繼承合適的抽象類。對于Excel,這包括提供一個 org.springframework.web.servlet.view.document.AbstractExcelView的子類,并實現 buildExcelDocument方法。
          package?com.zhupan.view;

          import?java.util.Date;
          import?java.util.Map;
          import?javax.servlet.http.HttpServletRequest;
          import?javax.servlet.http.HttpServletResponse;

          import?org.apache.poi.hssf.usermodel.HSSFCell;
          import?org.apache.poi.hssf.usermodel.HSSFCellStyle;
          import?org.apache.poi.hssf.usermodel.HSSFDataFormat;
          import?org.apache.poi.hssf.usermodel.HSSFRow;
          import?org.apache.poi.hssf.usermodel.HSSFSheet;
          import?org.apache.poi.hssf.usermodel.HSSFWorkbook;
          import?org.springframework.web.servlet.view.document.AbstractExcelView;


          public?class?ViewExcel?extends?AbstractExcelView?{

          ??
          public?void?buildExcelDocument(
          ?????????????Map?model,?HSSFWorkbook?workbook,
          ?????????????HttpServletRequest?request,?HttpServletResponse?response)
          ????
          throws?Exception?{
          ??
          ???????HSSFSheet?sheet?
          =?workbook.createSheet("list");
          ???????sheet.setDefaultColumnWidth((
          short)?12);
          ???????
          ???????
          ???????HSSFCell?cell?
          =?getCell(sheet,?0,?0);
          ???????setText(cell,?
          "Spring?Excel?test");
          ??
          ???????HSSFCellStyle?dateStyle?
          =?workbook.createCellStyle();
          ???????dateStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat(
          "m/d/yy"));
          ???????cell?
          =?getCell(sheet,?1,?0);
          ???????cell.setCellValue(
          new?Date());
          ???????cell.setCellStyle(dateStyle);
          ???????getCell(sheet,?
          2,?0).setCellValue(458);
          ??
          ???????HSSFRow?sheetRow?
          =?sheet.createRow(3);
          ???????
          for?(short?i?=?0;?i?<?10;?i++)?{
          ?????????????sheetRow.createCell(i).setCellValue(i?
          *?10);
          ???????}


          ??}

          ??
          }


          4、用于PDF視圖的視圖子類化
          需要象下面一樣繼承org.springframework.web.servlet.view.document.AbstractPdfView,并實現buildPdfDocument()方法。
          package?com.zhupan.view;

          import?java.util.List;
          import?java.util.Map;

          import?javax.servlet.http.HttpServletRequest;
          import?javax.servlet.http.HttpServletResponse;

          import?org.springframework.web.servlet.view.document.AbstractPdfView;

          import?com.lowagie.text.Document;
          import?com.lowagie.text.Paragraph;
          import?com.lowagie.text.pdf.PdfWriter;

          public?class?ViewPDF?extends?AbstractPdfView?{
          ????
          public?void?buildPdfDocument(Map?model,?Document?document,
          ????????????PdfWriter?writer,?HttpServletRequest?request,
          ????????????HttpServletResponse?response)?
          throws?Exception?{

          ????????List?list?
          =?(List)?model.get("list");

          ????????
          for?(int?i?=?0;?i?<?list.size();?i++)
          ????????????document.add(
          new?Paragraph((String)?list.get(i)));
          ????}


          }

          5、其他文件
          1)控制器ViewController
          package?com.zhupan.spring;

          import?java.util.ArrayList;
          import?java.util.HashMap;
          import?java.util.List;
          import?java.util.Map;

          import?javax.servlet.http.HttpServletRequest;
          import?javax.servlet.http.HttpServletResponse;

          import?org.springframework.web.servlet.ModelAndView;
          import?org.springframework.web.servlet.mvc.multiaction.MultiActionController;

          import?com.zhupan.view.ViewExcel;
          import?com.zhupan.view.ViewPDF;


          public?class?ViewController?extends?MultiActionController{
          ?????
          ?????
          public?ModelAndView?viewPDF(HttpServletRequest?request,?HttpServletResponse?response)?throws?Exception?{
          ???????List?list?
          =?new?ArrayList();
          ???????Map?model
          =new?HashMap();
          ???????list.add(
          "test1");
          ???????list.add(
          "test2");
          ???????model.put(
          "list",list);
          ???????ViewPDF?viewPDF
          =new?ViewPDF();
          ???????
          return?new?ModelAndView(viewPDF,model);
          ??}

          ?????
          ??????
          public?ModelAndView?viewExcel(HttpServletRequest?request,?HttpServletResponse?response)?throws?Exception?{
          ????????????List?list?
          =?new?ArrayList();
          ????????Map?model
          =new?HashMap();
          ????????list.add(
          "test1");
          ????????list.add(
          "test2");
          ????????model.put(
          "list",list);
          ????????ViewExcel?viewExcel
          =new?ViewExcel();
          ????????
          return?new?ModelAndView(viewExcel,model);
          ??????}

          }
          2)web.xml
          <?xml?version="1.0"?encoding="UTF-8"?>
          <web-app?version="2.4"?xmlns="http://java.sun.com/xml/ns/j2ee"
          ????xmlns:xsi
          ="http://www.w3.org/2001/XMLSchema-instance"
          ????xsi:schemaLocation
          ="http://java.sun.com/xml/ns/j2ee?
          ????http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
          >

          ????
          <display-name>springPDFTest</display-name>
          ????
          <servlet>
          ????????
          <servlet-name>springPDFTest</servlet-name>
          ????????
          <servlet-class>
          ????????????org.springframework.web.servlet.DispatcherServlet
          ????????
          </servlet-class>
          ????????
          <load-on-startup>1</load-on-startup>
          ????
          </servlet>

          ????
          <servlet-mapping>
          ????????
          <servlet-name>springPDFTest</servlet-name>
          ????????
          <url-pattern>*.shtml</url-pattern>
          ????
          </servlet-mapping>

          ????
          <welcome-file-list>
          ????????
          <welcome-file>index.jsp</welcome-file>
          ????
          </welcome-file-list>

          </web-app>

          3)index.jsp
          <%@?page?contentType="text/html;?charset=gb2312"%>

          <a?href="viewPDF.shtml">PDF視圖打開?</a>
          <br>
          <a?href="viewExcel.shtml">Excel視圖打開</a>

          posted @ 2006-10-07 13:29 nbt 閱讀(639) | 評論 (0)編輯 收藏

          Eclipse快速上手指南之使用Ant

          ????????????????????????????????????作者:佚名 ????來自:J2ME開發網

          Ant是Java平臺下非常棒的批處理命令執行程序,能自動完成編譯,測試,打包,部署等等一系列任務。

            Ant是Java平臺下非常棒的批處理命令執行程序,能非常方便地自動完成編譯,測試,打包,部署等等一系列任務,大大提高開發效率。如果你現在還沒有開始使用Ant,那就要趕快開始學習使用,使自己的開發水平上一個新臺階。

            Eclipse 中已經集成了Ant,我們可以直接在Eclipse中運行Ant。

            以前面建立的Hello工程為例,創建以下目錄結構:

            新建一個build.xml,放在工程根目錄下。build.xml定義了Ant要執行的批處理命令。雖然Ant也可以使用其它文件名,但是遵循標準能更使開發更規范,同時易于與別人交流。

            通常,src存放Java源文件,classes存放編譯后的class文件,lib存放編譯和運行用到的所有jar文件,web存放JSP等web文件,dist存放打包后的jar文件,doc存放API文檔。

            然后在根目錄下創建build.xml文件,輸入以下內容:

          <xml version="1.0"?>
          <project name="Hello world" default="doc">

          <-- properies -->
          <property name="src.dir" value="src" />
          <property name="report.dir" value="report" />
          <property name="classes.dir" value="classes" />
          <property name="lib.dir" value="lib" />
          <property name="dist.dir" value="dist" />
          <property name="doc.dir" value="doc"/>

          <-- 定義classpath -->
          <path id="master-classpath">
          <fileset file="${lib.dir}/*.jar" />
          <pathelement path="${classes.dir}"/>
          <path>

          <-- 初始化任務 -->
          <target name="init">
          <target>

          <-- 編譯 -->
          <target name="compile" depends="init" description="compile the source files">
          <mkdir dir="${classes.dir}"/>
          <javac srcdir="${src.dir}" destdir="${classes.dir}" target="1.4">
          <classpath refid="master-classpath"/>
          <javac>
          <target>

          <-- 測試 -->
          <target name="test" depends="compile" description="run junit test">
          <mkdir dir="${report.dir}"/>
          <junit printsummary="on"
          haltonfailure="false"
          failureproperty="tests.failed"
          showoutput="true">
          <classpath refid="master-classpath" />
          <ormatter type="plain"/>
          <batchtest todir="${report.dir}">
          <fileset dir="${classes.dir}">
          <include name="**/*Test.*"/>
          <fileset>
          <batchtest>
          <junit>
          <fail if="tests.failed">
          ***********************************************************
          **** One or more tests failed! Check the output ... ****
          ***********************************************************
          <fail/>
          <target/>

          <-- 打包成jar -->
          <target name="pack" depends="test" description="make .jar file">
          <mkdir dir="${dist.dir}" />
          <jar destfile="${dist.dir}/hello.jar" basedir="${classes.dir}">
          <xclude name="**/*Test.*" />
          <xclude name="**/Test*.*" />
          <jar/>
          <targe/t>

          <-- 輸出api文檔 -->
          <target name="doc" depends="pack" description="create api doc">
          <mkdir dir="${doc.dir}" />
          <javadoc destdir="${doc.dir}"
          author="true"
          version="true"
          use="true"
          windowtitle="Test API">
          <packageset dir="${src.dir}" defaultexcludes="yes">
          <include name="example/**" />
          <packageset/>
          <doctitle>[CDATA[<1>ello, test<h1>]>doctitle>
          <dottom>[CDATA[<>ll Rights Reserved.<i>]>bottom>
          <tag name="todo" scope="all" description="To do:" />
          <javadoc/>
          <target/>
          <project/>

            以上xml依次定義了init(初始化),compile(編譯),test(測試),doc(生成文檔),pack(打包)任務,可以作為模板。

            選中Hello工程,然后選擇“Project”,“Properties”,“Builders”,“New…”,選擇“Ant Build”:

            填入Name:Ant_Builder;Buildfile:build.xml;Base Directory:${workspace_loc:/Hello}(按“Browse Workspace”選擇工程根目錄),由于用到了junit.jar包,搜索Eclipse目錄,找到junit.jar,把它復制到Hello/lib目錄下,并添加到Ant的Classpath中:

            然后在Builder面板中鉤上Ant_Build,去掉Java Builder:

            再次編譯,即可在控制臺看到Ant的輸出:

          Buildfile: F:\eclipse-projects\Hello\build.xml

          init:

          compile:
          [mkdir] Created dir: F:\eclipse-projects\Hello\classes
          [javac] Compiling 2 source files to F:\eclipse-projects\Hello\classes

          test:
          [mkdir] Created dir: F:\eclipse-projects\Hello\report
          [junit] Running example.HelloTest
          [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.02 sec

          pack:
          [mkdir] Created dir: F:\eclipse-projects\Hello\dist
          [jar] Building jar: F:\eclipse-projects\Hello\dist\hello.jar

          doc:
          [mkdir] Created dir: F:\eclipse-projects\Hello\doc
          [javadoc] Generating Javadoc
          [javadoc] Javadoc execution
          [javadoc] Loading source files for package example...
          [javadoc] Constructing Javadoc information...
          [javadoc] Standard Doclet version 1.4.2_04
          [javadoc] Building tree for all the packages and classes...
          [javadoc] Building index for all the packages and classes...
          [javadoc] Building index for all classes...
          [javadoc] Generating F:\eclipse-projects\Hello\doc\stylesheet.css...
          [javadoc] Note: Custom tags that could override future standard tags: @todo. To avoid potential overrides, use at least one period character (.) in custom tag names.
          [javadoc] Note: Custom tags that were not seen: @todo
          BUILD SUCCESSFUL
          Total time: 11 seconds

            Ant依次執行初始化,編譯,測試,打包,生成API文檔一系列任務,極大地提高了開發效率。將來開發J2EE項目時,還可加入部署等任務。并且,即使脫離了Eclipse環境,只要正確安裝了Ant,配置好環境變量ANT_HOME=<nt解壓目錄>Path=…;%ANT_HOME%\bin,在命令行提示符下切換到Hello目錄,簡單地鍵入ant即可。

          posted @ 2006-08-14 09:34 nbt 閱讀(540) | 評論 (1)編輯 收藏

          JAR 文件是什么?


          JAR?文件格式以流行的?ZIP?文件格式為基礎,用于將許多個文件聚集為一個文件。與?ZIP?文件不同的是,JAR?文件不僅用于壓縮和發布,而且還用于部署和封裝庫、組件和插件程序,并可被像編譯器和?JVM?這樣的工具直接使用。在?JAR?中包含特殊的文件,如?manifests?和部署描述符,用來指示工具如何處理特定的?JAR。?
          一個?JAR?文件可以用于:

          □?用于發布和使用類庫?

          □?作為應用程序和擴展的構建單元?

          □?作為組件、applet?或者插件程序的部署單位?

          □?用于打包與組件相關聯的輔助資源?
          JAR?文件格式提供了許多優勢和功能,其中很多是傳統的壓縮格式如?ZIP?或者?TAR?所沒有提供的。它們包括:
          ☆?安全性。?可以對?JAR?文件內容加上數字化簽名。這樣,能夠識別簽名的工具就可以有選擇地為您授予軟件安全特權,這是其他文件做不到的,它還可以檢測代碼是否被篡改過。
          ☆?減少下載時間。?如果一個?applet?捆綁到一個?JAR?文件中,那么瀏覽器就可以在一個?HTTP?事務中下載這個?applet?的類文件和相關的資源,而不是對每一個文件打開一個新連接。
          ☆?壓縮。JAR?格式允許您壓縮文件以提高存儲效率。
          ☆?傳輸平臺擴展。?Java?擴展框架(Java?Extensions?Framework)提供了向?Java?核心平臺添加功能的方法,這些擴展是用?JAR?文件打包的(Java?3D?和?JavaMail?就是由?Sun?開發的擴展例子)。
          ☆?包密封。?存儲在?JAR?文件中的包可以選擇進行密封,以增強版本一致性和安全性。密封一個包意味著包中的所有類都必須在同一?JAR?文件中找到。
          ☆?包版本控制。?一個?JAR?文件可以包含有關它所包含的文件的數據,如廠商和版本信息。
          ☆?可移植性。?處理?JAR?文件的機制是?Java?平臺核心?API?的標準部分。?
          壓縮的和未壓縮的?JAR

          jar?工具在默認情況下壓縮文件。未壓縮的?JAR?文件一般可以比壓縮過的?JAR?文件更快地裝載,因為在裝載過程中要解壓縮文件,但是未壓縮的文件在網絡上的下載時間可能更長。
          META-INF?目錄

          大多數?JAR?文件包含一個?META-INF?目錄,它用于存儲包和擴展的配置數據,如安全性和版本信息。Java?2?平臺識別并解釋?META-INF?目錄中的下述文件和目錄,以便配置應用程序、擴展和類裝載器:
          ☆?MANIFEST.MF。?這個?manifest?文件定義了與擴展和包相關的數據。
          ☆?INDEX.LIST。?這個文件由?jar?工具的新選項?-i?生成,它包含在應用程序或者擴展中定義的包的位置信息。它是?JarIndex?實現的一部分,并由類裝載器用于加速類裝載過程。
          ☆?xxx.SF。?這是?JAR?文件的簽名文件。占位符?xxx?標識了簽名者。
          ☆?xxx.DSA。?與簽名文件相關聯的簽名程序塊文件,它存儲了用于簽名?JAR?文件的公共簽名。?
          jar?工具

          為了用?JAR?文件執行基本的任務,要使用作為Java?Development?Kit?的一部分提供的?Java?Archive?Tool?(jar?工具)。用?jar?命令調用?jar?工具。表?1?顯示了一些常見的應用:
          表?1.?常見的?jar?工具用法?
          功能????命令
          用一個單獨的文件創建一個?JAR?文件????jar?cf?jar-file?input-file...
          用一個目錄創建一個?JAR?文件????jar?cf?jar-file?dir-name
          創建一個未壓縮的?JAR?文件????jar?cf0?jar-file?dir-name
          更新一個?JAR?文件????jar?uf?jar-file?input-file...
          查看一個?JAR?文件的內容????jar?tf?jar-file
          提取一個?JAR?文件的內容????jar?xf?jar-file
          從一個?JAR?文件中提取特定的文件????jar?xf?jar-file?archived-file...
          運行一個打包為可執行?JAR?文件的應用程序????java?-jar?app.jar
          可執行的?JAR

          一個可執行的?jar?文件是一個自包含的?Java?應用程序,它存儲在特別配置的JAR?文件中,可以由?JVM?直接執行它而無需事先提取文件或者設置類路徑。要運行存儲在非可執行的?JAR?中的應用程序,必須將它加入到您的類路徑中,并用名字調用應用程序的主類。但是使用可執行的?JAR?文件,我們可以不用提取它或者知道主要入口點就可以運行一個應用程序。可執行?JAR?有助于方便發布和執行?Java?應用程序。
          創建可執行?JAR

          創建一個可執行?JAR?很容易。首先將所有應用程序代碼放到一個目錄中。假設應用程序中的主類是?com.mycompany.myapp.Sample。您要創建一個包含應用程序代碼的?JAR?文件并標識出主類。為此,在某個位置(不是在應用程序目錄中)創建一個名為?manifest?的文件,并在其中加入以下一行:
          Main-Class:?com.mycompany.myapp.Sample
          然后,像這樣創建?JAR?文件:
          jar?cmf?manifest?ExecutableJar.jar?application-dir
          所要做的就是這些了?--?現在可以用?java?-jar?執行這個?JAR?文件?ExecutableJar.jar。
          一個可執行的?JAR?必須通過?menifest?文件的頭引用它所需要的所有其他從屬?JAR。如果使用了?-jar?選項,那么環境變量?CLASSPATH?和在命令行中指定的所有類路徑都被?JVM?所忽略。
          啟動可執行?JAR

          既然我們已經將自己的應用程序打包到了一個名為?ExecutableJar.jar?的可執行?JAR?中了,那么我們就可以用下面的命令直接從文件啟動這個應用程序:
          java?-jar?ExecutableJar.jar
          包密封

          密封?JAR?文件中的一個包意味著在這個包中定義的所有類都必須在同一個?JAR?文件中找到。這使包的作者可以增強打包類之間的版本一致性。密封還提供了防止代碼篡改的手段。
          要密封包,需要在?JAR?的?manifest?文件中為包添加一個?Name?頭,然后加上值為“true”的?Sealed?頭。與可執行的?JAR?一樣,可以在創建?JAR?時,通過指定一個具有適當頭元素的?manifest?文件密封一個?JAR,如下所示:
          Name:?com/samplePackage/

          Sealed:?true
          Name?頭標識出包的相對路徑名。它以一個“/”結束以與文件名區別。在?Name?頭后面第一個空行之前的所有頭都作用于在?Name?頭中指定的文件或者包。在上述例子中,因為?Sealed?頭出現在?Name?頭后并且中間沒有空行,所以?Sealed?頭將被解釋為只應用到包?com/samplePackage?上。
          如果試圖從密封包所在的?JAR?文件以外的其他地方裝載密封包中的一個類,那么?JVM?將拋出一個?SecurityException。
          擴展打包

          擴展為?Java?平臺增加了功能,在?JAR?文件格式中已經加入了擴展機制。擴展機制使得?JAR?文件可以通過?manifest?文件中的?Class-Path?頭指定所需要的其他?JAR?文件。
          假設?extension1.jar?和?extension2.jar?是同一個目錄中的兩個?JAR?文件,extension1.jar?的?manifest?文件包含以下頭:
          Class-Path:?extension2.jar
          這個頭表明?extension2.jar?中的類是?extension1.jar?中的類的擴展類。extension1.jar?中的類可以調用?extension2.jar?中的類,并且不要求?extension2.jar?處在類路徑中。
          在裝載使用擴展機制的?JAR?時,JVM?會高效而自動地將在Class-Path?頭中引用的?JAR?添加到類路徑中。不過,擴展?JAR?路徑被解釋為相對路徑,所以一般來說,擴展?JAR?必須存儲在引用它的?JAR?所在的同一目錄中。
          例如,假設類?ExtensionClient?引用了類?ExtensionDemo,它捆綁在一個名為?ExtensionClient.jar?的?JAR?文件中,而類?ExtensionDemo?則捆綁在?ExtensionDemo.jar?中。為了使?ExtensionDemo.jar?可以成為擴展,必須將?ExtensionDemo.jar?列在?ExtensionClient.jar?的?manifest?的?Class-Path?頭中,如下所示:
          Manifest-Version:?1.0

          Class-Path:?ExtensionDemo.jar
          在這個?manifest?中?Class-Path?頭的值是沒有指定路徑的?ExtensionDemo.jar,表明?ExtensionDemo.jar?與?ExtensionClient?JAR?文件處在同一目錄中。
          JAR?文件中的安全性

          JAR?文件可以用?jarsigner?工具或者直接通過?java.security?API?簽名。一個簽名的?JAR?文件與原來的?JAR?文件完全相同,只是更新了它的?manifest,并在?META-INF?目錄中增加了兩個文件,一個簽名文件和一個簽名塊文件。
          JAR?文件是用一個存儲在?Keystore?數據庫中的證書簽名的。存儲在?keystore?中的證書有密碼保護,必須向?jarsigner?工具提供這個密碼才能對?JAR?文件簽名。
          ?

          圖?1.?Keystore?數據庫
          JAR?的每一位簽名者都由在?JAR?文件的?META-INF?目錄中的一個具有?.SF?擴展名的簽名文件表示。這個文件的格式類似于?manifest?文件?--?一組?RFC-822?頭。如下所示,它的組成包括一個主要部分,它包括了由簽名者提供的信息、但是不特別針對任何特定的?JAR?文件項,還有一系列的單獨的項,這些項也必須包含在?menifest?文件中。在驗證一個簽名的?JAR?時,將簽名文件的摘要值與對?JAR?文件中的相應項計算的摘要值進行比較。
          清單?1.?簽名?JAR?中的?Manifest?和?signature?文件
          Contents?of?signature?file?META-INF/MANIFEST.MF

          Manifest-Version:?1.0

          Created-By:?1.3.0?(Sun?Microsystems?Inc.)

          Name:?Sample.java

          SHA1-Digest:?3+DdYW8INICtyG8ZarHlFxX0W6g=

          Name:?Sample.class

          SHA1-Digest:?YJ5yQHBZBJ3SsTNcHJFqUkfWEmI=

          Contents?of?signature?file?META-INF/JAMES.SF

          Signature-Version:?1.0

          SHA1-Digest-Manifest:?HBstZOJBuuTJ6QMIdB90T8sjaOM=

          Created-By:?1.3.0?(Sun?Microsystems?Inc.)

          Name:?Sample.java

          SHA1-Digest:?qipMDrkurQcKwnyIlI3Jtrnia8Q=

          Name:?Sample.class

          SHA1-Digest:?pT2DYby8QXPcCzv2NwpLxd8p4G4=
          數字簽名

          一個數字簽名是.SF?簽名文件的已簽名版本。數字簽名文件是二進制文件,并且與?.SF?文件有相同的文件名,但是擴展名不同。根據數字簽名的類型?--?RSA、DSA?或者?PGP?--?以及用于簽名?JAR?的證書類型而有不同的擴展名。
          Keystore

          要簽名一個?JAR?文件,必須首先有一個私鑰。私鑰及其相關的公鑰證書存儲在名為?keystores?的、有密碼保護的數據庫中。JDK?包含創建和修改?keystores?的工具。keystore?中的每一個密鑰都可以用一個別名標識,它通常是擁有這個密鑰的簽名者的名字。
          所有?keystore?項(密鑰和信任的證書項)都是用唯一別名訪問的。別名是在用?keytool?-genkey?命令生成密鑰對(公鑰和私鑰)并在?keystore?中添加項時指定的。之后的?keytool?命令必須使用同樣的別名引用這一項。
          例如,要用別名“james”生成一個新的公鑰/私鑰對并將公鑰包裝到自簽名的證書中,要使用下述命令:
          keytool?-genkey?-alias?james?-keypass?jamespass?

          -validity?80?-keystore?jamesKeyStore?

          -storepass?jamesKeyStorePass
          這個命令序列指定了一個初始密碼“jamespass”,后續的命令在訪問?keystore?“jamesKeyStore”中與別名“james”相關聯的私鑰時,就需要這個密碼。如果?keystore“jamesKeyStore”不存在,則?keytool?會自動創建它。
          jarsigner?工具

          jarsigner?工具使用?keystore?生成或者驗證?JAR?文件的數字簽名。
          假設像上述例子那樣創建了?keystore?“jamesKeyStore”,并且它包含一個別名為“james”的密鑰,可以用下面的命令簽名一個?JAR?文件:
          jarsigner?-keystore?jamesKeyStore?-storepass?jamesKeyStorePass?

          -keypass?jamespass?-signedjar?SSample.jar?Sample.jar?james
          這個命令用密碼“jamesKeyStorePass”從名為“jamesKeyStore”的?keystore?中提出別名為“james”、密碼為“jamespass”的密鑰,并對?Sample.jar?文件簽名、創建一個簽名的?JAR?--?SSample.jar。
          jarsigner?工具還可以驗證一個簽名的?JAR?文件,這種操作比簽名?JAR?文件要簡單得多,只需執行以下命令:
          jarsigner?-verify?SSample.jar
          如果簽名的?JAR?文件沒有被篡改過,那么?jarsigner?工具就會告訴您?JAR?通過驗證了。否則,它會拋出一個?SecurityException,?表明哪些文件沒有通過驗證。
          還可以用?java.util.jar?和?java.security?API?以編程方式簽名?JAR(有關細節參閱參考資料)。也可以使用像?Netscape?Object?Signing?Tool?這樣的工具。
          JAR?索引

          如果一個應用程序或者?applet?捆綁到多個?JAR?文件中,那么類裝載器就使用一個簡單的線性搜索算法搜索類路徑中的每一個元素,這使類裝載器可能要下載并打開許多個?JAR?文件,直到找到所要的類或者資源。如果類裝載器試圖尋找一個不存在的資源,那么在應用程序或者?applet?中的所有?JAR?文件都會下載。對于大型的網絡應用程序和?applet,這會導致啟動緩慢、響應遲緩并浪費帶寬。
          從?JDK?1.3?以后,JAR?文件格式開始支持索引以優化網絡應用程序中類的搜索過程,特別是?applet。JarIndex?機制收集在?applet?或者應用程序中定義的所有?JAR?文件的內容,并將這些信息存儲到第一個?JAR?文件中的索引文件中。下載了第一個?JAR?文件后,applet?類裝載器將使用收集的內容信息高效地裝載?JAR?文件。這個目錄信息存儲在根?JAR?文件的?META-INF?目錄中的一個名為?INDEX.LIST?的簡單文本文件中。
          創建一個?JarIndex

          可以通過在?jar?命令中指定?-i?選項創建一個?JarIndex。假設我們的目錄結構如下圖所示:
          ?

          圖?2.?JarIndex
          您將使用下述命令為?JarIndex_Main.jar、JarIndex_test.jar?和?JarIndex_test1.jar?創建一個索引文件:
          jar?-i?JarIndex_Main.jar?JarIndex_test.jar?SampleDir/JarIndex_test1.jar?
          INDEX.LIST?文件的格式很簡單,包含每個已索引的?JAR?文件中包含的包或者類的名字,如清單?2?所示:
          清單?2.?JarIndex?INDEX.LIST?文件示例
          JarIndex-Version:?1.0

          JarIndex_Main.jar

          sp

          JarIndex_test.jar

          Sample

          SampleDir/JarIndex_test1.jar

          org

          org/apache

          org/apache/xerces

          org/apache/xerces/framework

          org/apache/xerces/framework/xml4j
          結束語?

          JAR?格式遠遠超出了一種壓縮格式,它有許多可以改進效率、安全性和組織?Java?應用程序的功能。因為這些功能已經建立在核心平臺?--?包括編譯器和類裝載器?--?中了,所以開發人員可以利用?JAR?文件格式的能力簡化和改進開發和部署過程。

          posted @ 2006-08-09 16:26 nbt 閱讀(1134) | 評論 (0)編輯 收藏

          JAR文件包及jar命令詳解

          常常在網上看到有人詢問:如何把?java?程序編譯成?.exe?文件。通常回答只有兩種,一種是制作一個可執行的?JAR?文件包,然后就可以像.chm?文檔一樣雙擊運行了;而另一種是使用?JET?來進行?編譯。但是?JET?是要用錢買的,而且據說?JET?也不是能把所有的?Java?程序都編譯成執行文件,性能也要打些折扣。所以,使用制作可執行?JAR?文件包的方法就是最佳選擇了,何況它還能保持?Java?的跨平臺特性。?

            下面就來看看什么是?JAR?文件包吧:?

            1.?JAR?文件包?

            JAR?文件就是?Java?Archive?File,顧名思意,它的應用是與?Java?息息相關的,是?Java?的一種文檔格式。JAR?文件非常類似?ZIP?文件??準確的說,它就是?ZIP?文件,所以叫它文件包。JAR?文件與?ZIP?文件唯一的區別就是在?JAR?文件的內容中,包含了一個?META-INF/MANIFEST.MF?文件,這個文件是在生成?JAR?文件的時候自動創建的。舉個例子,如果我們具有如下目錄結構的一些文件:?

            ==?

            `--?test?

             ?`--?Test.class?

            把它壓縮成?ZIP?文件?test.zip,則這個?ZIP?文件的內部目錄結構為:?

            test.zip?

            `--?test?

             ?`--?Test.class?

            如果我們使用?JDK?的?jar?命令把它打成?JAR?文件包?test.jar,則這個?JAR?文件的內部目錄結構為:?

            test.jar?

            |--?META-INF?

            | ?`--?MANIFEST.MF?

            `--?test?

              `--Test.class?

            2.?創建可執行的?JAR?文件包?

            制作一個可執行的?JAR?文件包來發布你的程序是?JAR?文件包最典型的用法。?

            Java?程序是由若干個?.class?文件組成的。這些?.class?文件必須根據它們所屬的包不同而分級分目錄存放;運行前需要把所有用到的包的根目錄指定給?CLASSPATH?環境變量或者?java?命令的?-cp?參數;運行時還要到控制臺下去使用?java?命令來運行,如果需要直接雙擊運行必須寫?Windows?的批處理文件?(.bat)?或者?Linux?的?Shell?程序。因此,許多人說,Java?是一種方便開發者苦了用戶的程序設計語言。?

            其實不然,如果開發者能夠制作一個可執行的?JAR?文件包交給用戶,那么用戶使用起來就方便了。在?Windows?下安裝?JRE?(Java?Runtime?Environment)?的時候,安裝文件會將?.jar?文件映射給?javaw.exe?打開。那么,對于一個可執行的?JAR?文件包,用戶只需要雙擊它就可以運行程序了,和閱讀?.chm?文檔一樣方便?(.chm?文檔默認是由?hh.exe?打開的)。那么,現在的關鍵,就是如何來創建這個可執行的?JAR?文件包。?

            創建可執行的?JAR?文件包,需要使用帶?cvfm?參數的?jar?命令,同樣以上述?test?目錄為例,命令如下:?

          jar?cvfm?test.jar?manifest.mf?test?

            這里?test.jar?和?manifest.mf?兩個文件,分別是對應的參數?f?和?m,其重頭戲在?manifest.mf。因為要創建可執行的?JAR?文件包,光靠指定一個?manifest.mf?文件是不夠的,因為?MANIFEST?是?JAR?文件包的特征,可執行的?JAR?文件包和不可執行的?JAR?文件包都包含?MANIFEST。關鍵在于可執行?JAR?文件包的?MANIFEST,其內容包含了?Main-Class?一項。這在?MANIFEST?中書寫格式如下:?

            Main-Class:?可執行主類全名(包含包名)?

            例如,假設上例中的?Test.class?是屬于?test?包的,而且是可執行的類?(定義了?public?static?void?main(String[])?方法),那么這個?manifest.mf?可以編輯如下:?

          Main-Class:?test.Test?<回車>?

            這個?manifest.mf?可以放在任何位置,也可以是其它的文件名,只需要有?Main-Class:?test.Test?一行,且該行以一個回車符結束即可。創建了?manifest.mf?文件之后,我們的目錄結構變為:?

            ==?

            |--?test?

            | ?`--?Test.class?

            `--?manifest.mf?

            這時候,需要到?test?目錄的上級目錄中去使用?jar?命令來創建?JAR?文件包。也就是在目錄樹中使用“==”表示的那個目錄中,使用如下命令:?

          jar?cvfm?test.jar?manifest.mf?test?

            之后在“==”目錄中創建了?test.jar,這個?test.jar?就是執行的?JAR?文件包。運行時只需要使用?java?-jar?test.jar?命令即可。?

            需要注意的是,創建的?JAR?文件包中需要包含完整的、與?Java?程序的包結構對應的目錄結構,就像上例一樣。而?Main-Class?指定的類,也必須是完整的、包含包路徑的類名,如上例的?test.Test;而且在沒有打成?JAR?文件包之前可以使用?java?<類名>?來運行這個類,即在上例中?java?test.Test?是可以正確運行的?(當然要在?CLASSPATH?正確的情況下)。?
           3.?jar?命令詳解?

            jar?是隨?JDK?安裝的,在?JDK?安裝目錄下的?bin?目錄中,Windows?下文件名為?jar.exe,Linux?下文件名為?jar。它的運行需要用到?JDK?安裝目錄下?lib?目錄中的?tools.jar?文件。不過我們除了安裝?JDK?什么也不需要做,因為?SUN?已經幫我們做好了。我們甚至不需要將?tools.jar?放到?CLASSPATH?中。?

            使用不帶任何的?jar?命令我們可以看到?jar?命令的用法如下:?

            jar?{ctxu}[vfm0M]?[jar-文件]?[manifest-文件]?[-C?目錄]?文件名?...?

            其中?{ctxu}?是?jar?命令的子命令,每次?jar?命令只能包含?ctxu?中的一個,它們分別表示:?

             -c 創建新的?JAR?文件包?

             -t 列出?JAR?文件包的內容列表?

             -x 展開?JAR?文件包的指定文件或者所有文件?

             -u 更新已存在的?JAR?文件包?(添加文件到?JAR?文件包中)?

               [vfm0M]?中的選項可以任選,也可以不選,它們是?jar?命令的選項參數?

             -v 生成詳細報告并打印到標準輸出?

             -f 指定?JAR?文件名,通常這個參數是必須的?

             -m 指定需要包含的?MANIFEST?清單文件?

             -0 只存儲,不壓縮,這樣產生的?JAR?文件包會比不用該參數產生的體積大,但速度更快?

             -M 不產生所有項的清單(MANIFEST〕文件,此參數會忽略?-m?參數?

               [jar-文件]?即需要生成、查看、更新或者解開的?JAR?文件包,它是?-f?參數的附屬參數?

               [manifest-文件]?即?MANIFEST?清單文件,它是?-m?參數的附屬參數?

               [-C?目錄]?表示轉到指定目錄下去執行這個?jar?命令的操作。它相當于先使用?cd?命令轉該目錄下再執行不帶?-C?參數的?jar?命令,它只能在創建和更新?JAR?文件包的時候可用。  ?

            文件名?...?指定一個文件/目錄列表,這些文件/目錄就是要添加到?JAR?文件包中的文件/目錄。如果指定了目錄,那么?jar?命令打包的時候會自動把該目錄中的所有文件和子目錄打入包中。?

            下面舉一些例子來說明?jar?命令的用法:?

            1)?jar?cf?test.jar?test?

            該命令沒有執行過程的顯示,執行結果是在當前目錄生成了?test.jar?文件。如果當前目錄已經存在?test.jar,那么該文件將被覆蓋。?

            2)?jar?cvf?test.jar?test?

            該命令與上例中的結果相同,但是由于?v?參數的作用,顯示出了打包過程,如下:?

            標明清單(manifest)?

            增加:test/(讀入=?0)?(寫出=?0)(存儲了?0%)?

            增加:test/Test.class(讀入=?7)?(寫出=?6)(壓縮了?14%)?

            3)?jar?cvfM?test.jar?test?

            該命令與?2)?結果類似,但在生成的?test.jar?中沒有包含?META-INF/MANIFEST?文件,打包過程的信息也略有差別:?

            增加:test/(讀入=?0)?(寫出=?0)(存儲了?0%)?

            增加:test/Test.class(讀入=?7)?(寫出=?6)(壓縮了?14%)?

            4)?jar?cvfm?test.jar?manifest.mf?test?

            運行結果與?2)?相似,顯示信息也相同,只是生成?JAR?包中的?META-INF/MANIFEST?內容不同,是包含了?manifest.mf?的內容?

            5)?jar?tf?test.jar?

            在?test.jar?已經存在的情況下,可以查看?test.jar?中的內容,如對于?2)?和?3)?生成的?test.jar?分別應該此命令,結果如下;?

            對于?2)?

            META-INF/?

            META-INF/MANIFEST.MF?

            test/?

            test/Test.class?

            對于?3)?

            test/?

            test/Test.class?

            6)?jar?tvf?test.jar?

            除顯示?5)?中顯示的內容外,還包括包內文件的詳細信息,如:?

            0?Wed?Jun?19?15:39:06?GMT?2002?META-INF/?

            86?Wed?Jun?19?15:39:06?GMT?2002?META-INF/MANIFEST.MF?

            0?Wed?Jun?19?15:33:04?GMT?2002?test/?

            7?Wed?Jun?19?15:33:04?GMT?2002?test/Test.class?

            7)?jar?xf?test.jar?

            解開?test.jar?到當前目錄,不顯示任何信息,對于?2)?生成的?test.jar,解開后的目錄結構如下:?

            ==?

            |--?META-INF?

            | ?`--?MANIFEST?

            `--?test?

              `--Test.class?

          jar?xvf?test.jar?

            運行結果與?7)?相同,對于解壓過程有詳細信息顯示,如:?

            創建:META-INF/?

            展開:META-INF/MANIFEST.MF?

            創建:test/?

            展開:test/Test.class?

            9)?jar?uf?test.jar?manifest.mf?

            在?test.jar?中添加了文件?manifest.mf,此使用?jar?tf?來查看?test.jar?可以發現?test.jar?中比原來多了一個?manifest。這里順便提一下,如果使用?-m?參數并指定?manifest.mf?文件,那么?manifest.mf?是作為清單文件?MANIFEST?來使用的,它的內容會被添加到?MANIFEST?中;但是,如果作為一般文件添加到?JAR?文件包中,它跟一般文件無異。?

            10)?jar?uvf?test.jar?manifest.mf?

            與?9)?結果相同,同時有詳細信息顯示,如:?

            增加:manifest.mf(讀入=?17)?(寫出=?19)(壓縮了?-11%)?

            4.?關于?JAR?文件包的一些技巧?

            1)?使用?unzip?來解壓?JAR?文件?

            在介紹?JAR?文件的時候就已經說過了,JAR?文件實際上就是?ZIP?文件,所以可以使用常見的一些解壓?ZIP?文件的工具來解壓?JAR?文件,如?Windows?下的?WinZip、WinRAR?等和?Linux?下的?unzip?等。使用?WinZip?和?WinRAR?等來解壓是因為它們解壓比較直觀,方便。而使用?unzip,則是因為它解壓時可以使用?-d?參數指定目標目錄。?

            在解壓一個?JAR?文件的時候是不能使用?jar?的?-C?參數來指定解壓的目標的,因為?-C?參數只在創建或者更新包的時候可用。那么需要將文件解壓到某個指定目錄下的時候就需要先將這具?JAR?文件拷貝到目標目錄下,再進行解壓,比較麻煩。如果使用?unzip,就不需要這么麻煩了,只需要指定一個?-d?參數即可。如:?

            unzip?test.jar?-d?dest/?

            2)?使用?WinZip?或者?WinRAR?等工具創建?JAR?文件?

            上面提到?JAR?文件就是包含了?META-INF/MANIFEST?的?ZIP?文件,所以,只需要使用?WinZip、WinRAR?等工具創建所需要?ZIP?壓縮包,再往這個?ZIP?壓縮包中添加一個包含?MANIFEST?文件的?META-INF?目錄即可。對于使用?jar?命令的?-m?參數指定清單文件的情況,只需要將這個?MANIFEST?按需要修改即可。?

            3)?使用?jar?命令創建?ZIP?文件?

            有些?Linux?下提供了?unzip?命令,但沒有?zip?命令,所以需要可以對?ZIP?文件進行解壓,即不能創建?ZIP?文件。如要創建一個?ZIP?文件,使用帶?-M?參數的?jar?命令即可,因為?-M?參數表示制作?JAR?包的時候不添加?MANIFEST?清單,那么只需要在指定目標?JAR?文件的地方將?.jar?擴展名改為?.zip?擴展名,創建的就是一個不折不扣的?ZIP?文件了,如將上一節的第?3)?個例子略作改動:?

            jar?cvfM?test.zip?test

          posted @ 2006-08-09 16:23 nbt 閱讀(273) | 評論 (0)編輯 收藏

          觸發器設計技巧與實例

          ?????在數據庫設計中,有兩種方法可設定自動化的資料處理規則,一種是條件約束,
          一種是觸發器,一般而言,條件約束比觸發器較容易設定及維護,且執行效率較
          好,但條件約束只能對資料進行簡單的欄位檢核,當涉及到多表操作等復雜操
          作時,就要用到觸發器了.
          ????? 一個數據庫系統中有兩個虛擬表用于存儲在表中記錄改動的信息,分別
          ?是:
          ???????????????? 虛擬表Inserted??????????????????? 虛擬表Deleted

          在表記錄新增時?? 存放新增的記錄??????????????????????? 不存儲記錄
          ??????? 修改時?? 存放用來更新的新記錄????????????????? 存放更新前的記錄
          ??????? 刪除時?? 不存儲記錄??????????????????????????? 存放被刪除的記錄
          ?
          ????? 觸發器的種類及觸發時機
          ?After觸發器:觸發時機在資料已變動完成后,它將對變動資料進行必要的
          ????????????? 善后與處理,若發現有錯誤,則用事務回滾(Rollback Transaction)
          ????????????? 將此次操作所更動的資料全部回復。
          ?Istead of 觸發器:觸發時機在資料變動前發生,且資料如何變動取決于觸發器

          現在介紹一下創建觸發器的編寫格式:

          After類型:
          ??? Create Trigger? 觸發器名稱
          ??? on 表名
          ??? after 操作(insert,update)
          ??? as?
          ????? Sql語句

          Instead類型
          ??? Create Trigger 觸發器名稱
          ??? on 表名
          ??? Instead of 操作(update,delete)
          ??? as
          ????? Sql語句

          實例1:
          ???? 在訂單(表orders)中的訂購數量(列名為num)有變動時,觸發器會先到客戶(表Customer)中
          取得該用戶的信用等級(列名為Level),然后再到信用額度(Creit)中取出該等級
          許可的訂購數量上下限,最后比較訂單中的訂購數量是否符合限制。

          代碼:?????????
          ?????????? Create? Trigger num_check
          ?????????? on orders
          ?????????? after insert,update
          ?????????? as
          ?????????? if update(num)
          ???????????? begin
          ?????????????? if exists(select a.* from orders a join customer b on a.customerid=b.customerid
          ????????????????????????????????????????????????? join creit c on b.level=c.level
          ????????????????????????????????????????????????? where a.num between c.up and c.down)
          ?????????????? begin
          ????????????????? rollback transaction
          ????????????????? exec master..xp_sendmail 'administrator','客戶的訂購數量不符合限制'
          ?????????????? end??
          ???????????? end?
          實例2:
          ????? 有工資管理系統中,當公司對某員工甲的月薪進行調整時,通常會先在表員工中修改薪資列,然后在
          ????? 表員工記錄中修改薪資調整時間與薪資
          ???????????
          ????????? Create trigger compensation
          ????????? on 員工
          ????????? after update
          ????????? as
          ??????????? if @@rowcount=0 return
          ??????????? if update(薪資)
          ?????????????? begin
          ???????????????? insert 員工記錄
          ???????????????? select 員工遍號,薪資,getdate()
          ???????????????? from inserted
          ?????????????? end

          posted @ 2006-08-07 12:09 nbt 閱讀(568) | 評論 (0)編輯 收藏

          收藏幾段SQL Server語句和存儲過程

          (轉載自--http://www.cnblogs.com/qiubole/articles/157309.html)


          -- ======================================================

          --列出SQL SERVER 所有表,字段名,主鍵,類型,長度,小數位數等信息

          --在查詢分析器里運行即可,可以生成一個表,導出到EXCEL中

          -- ======================================================

          SELECT

          ?????? (case when a.colorder=1 then d.name else '' end)表名,

          ?????? a.colorder 字段序號,

          ?????? a.name 字段名,

          ?????? (case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '√'else '' end) 標識,

          ?????? (case when (SELECT count(*)

          ?????? FROM sysobjects

          ?????? WHERE (name in

          ???????????????? (SELECT name

          ??????????????? FROM sysindexes

          ??????????????? WHERE (id = a.id) AND (indid in

          ????????????????????????? (SELECT indid

          ???????????????????????? FROM sysindexkeys

          ???????????????????????? WHERE (id = a.id) AND (colid in

          ?????????????????????????????????? (SELECT colid

          ????????????????????????????????? FROM syscolumns

          ????????????????????????????????? WHERE (id = a.id) AND (name = a.name))))))) AND

          ????????????? (xtype = 'PK'))>0 then '√' else '' end) 主鍵,

          ?????? b.name 類型,

          ?????? a.length 占用字節數,

          ?????? COLUMNPROPERTY(a.id,a.name,'PRECISION') as 長度,

          ?????? isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0) as 小數位數,

          ?????? (case when a.isnullable=1 then '√'else '' end) 允許空,

          ?????? isnull(e.text,'') 默認值,

          ?????? isnull(g.[value],'') AS 字段說明???

          ?

          FROM? syscolumns? a left join systypes b

          on? a.xtype=b.xusertype

          inner join sysobjects d

          on a.id=d.id? and? d.xtype='U' and? d.name<>'dtproperties'

          left join syscomments e

          on a.cdefault=e.id

          left join sysproperties g

          on a.id=g.id AND a.colid = g.smallid?

          order by a.id,a.colorder

          -------------------------------------------------------------------------------------------------

          ?

          ?

          ?

          ?

          ?

          ?

          列出SQL SERVER 所有表、字段定義,類型,長度,一個值等信息

          并導出到Excel 中

          -- ======================================================

          -- Export all user tables definition and one sample value

          -- jan-13-2003,Dr.Zhang

          -- ======================================================

          在查詢分析器里運行:

          SET ANSI_NULLS OFF

          GO

          SET NOCOUNT ON

          GO

          ?

          SET LANGUAGE 'Simplified Chinese'

          go

          DECLARE @tbl nvarchar(200),@fld nvarchar(200),@sql nvarchar(4000),@maxlen int,@sample nvarchar(40)

          ?

          SELECT d.name TableName,a.name FieldName,b.name TypeName,a.length Length,a.isnullable IS_NULL INTO #t

          FROM? syscolumns? a,? systypes b,sysobjects d?

          WHERE? a.xtype=b.xusertype? and? a.id=d.id? and? d.xtype='U'

          ?

          DECLARE read_cursor CURSOR

          FOR SELECT TableName,FieldName FROM #t

          ?

          SELECT TOP 1 '_TableName???????????????????? ' TableName,

          ??????????? 'FieldName????????????????????? ' FieldName,'TypeName???????????? ' TypeName,

          ??????????? 'Length' Length,'IS_NULL' IS_NULL,

          ??????????? 'MaxLenUsed' AS MaxLenUsed,'Sample Value????????? ' Sample,

          ???????????? 'Comment?? ' Comment INTO #tc FROM #t

          ?

          OPEN read_cursor

          ?

          FETCH NEXT FROM read_cursor INTO @tbl,@fld

          WHILE (@@fetch_status <> -1)? --- failes

          BEGIN

          ?????? IF (@@fetch_status <> -2) -- Missing

          ?????? BEGIN

          ????????????? SET @sql=N'SET @maxlen=(SELECT max(len(cast('+@fld+' as nvarchar))) FROM '+@tbl+')'

          ????????????? --PRINT @sql

          ????????????? EXEC SP_EXECUTESQL @sql,N'@maxlen int OUTPUT',@maxlen OUTPUT

          ????????????? --print @maxlen

          ????????????? SET @sql=N'SET @sample=(SELECT TOP 1 cast('+@fld+' as nvarchar) FROM '+@tbl+' WHERE len(cast('+@fld+' as nvarchar))='+convert(nvarchar(5),@maxlen)+')'

          ????????????? EXEC SP_EXECUTESQL @sql,N'@sample varchar(30) OUTPUT',@sample OUTPUT

          ????????????? --for quickly??

          ????????????? --SET @sql=N'SET @sample=convert(varchar(20),(SELECT TOP 1 '+@fld+' FROM '+

          ???????????????????? --@tbl+' order by 1 desc ))'?

          ????????????? PRINT @sql

          ????????????? print @sample

          ????????????? print @tbl

          ????????????? EXEC SP_EXECUTESQL @sql,N'@sample nvarchar(30) OUTPUT',@sample OUTPUT

          ????????????? INSERT INTO #tc SELECT *,ltrim(ISNULL(@maxlen,0)) as MaxLenUsed,

          ???????????????????? convert(nchar(20),ltrim(ISNULL(@sample,' '))) as Sample,' ' Comment FROM #t where TableName=@tbl and FieldName=@fld

          ?????? END

          ?????? FETCH NEXT FROM read_cursor INTO @tbl,@fld

          END

          ?

          CLOSE read_cursor

          DEALLOCATE read_cursor

          GO

          ?

          SET ANSI_NULLS ON

          GO

          SET NOCOUNT OFF

          GO

          select count(*)? from #t

          DROP TABLE #t

          GO

          ?

          select count(*)-1? from #tc

          ?

          select * into ##tx from #tc order by tablename

          DROP TABLE #tc

          ?

          --select * from ##tx

          ?

          declare @db nvarchar(60),@sql nvarchar(3000)

          set @db=db_name()

          --請修改用戶名和口令 導出到Excel 中

          set @sql='exec master.dbo.xp_cmdshell ''bcp ..dbo.##tx out c:\'+@db+'_exp.xls -w -C936 -Usa -Psa '''

          print @sql

          exec(@sql)

          GO

          DROP TABLE ##tx

          GO

          ?

          ?

          ?

          -- ======================================================

          --根據表中數據生成insert語句的存儲過程

          --建立存儲過程,執行 spGenInsertSQL 表名

          --感謝playyuer

          -- ======================================================

          CREATE?? proc spGenInsertSQL (@tablename varchar(256))

          ?

          as

          begin

          ? declare @sql varchar(8000)

          ? declare @sqlValues varchar(8000)

          ? set @sql =' ('

          ? set @sqlValues = 'values (''+'

          ? select @sqlValues = @sqlValues + cols + ' + '','' + ' ,@sql = @sql + '[' + name + '],'

          ??? from

          ??????? (select case

          ????????????????? when xtype in (48,52,56,59,60,62,104,106,108,122,127)???????????????????????????????

          ?????????????????????? then 'case when '+ name +' is null then ''NULL'' else ' + 'cast('+ name + ' as varchar)'+' end'

          ????????????????? when xtype in (58,61)

          ?????????????????????? then 'case when '+ name +' is null then ''NULL'' else '+''''''''' + ' + 'cast('+ name +' as varchar)'+ '+'''''''''+' end'

          ???????????????? when xtype in (167)

          ?????????????????????? then 'case when '+ name +' is null then ''NULL'' else '+''''''''' + ' + 'replace('+ name+','''''''','''''''''''')' + '+'''''''''+' end'

          ????????????????? when xtype in (231)

          ?????????????????????? then 'case when '+ name +' is null then ''NULL'' else '+'''N'''''' + ' + 'replace('+ name+','''''''','''''''''''')' + '+'''''''''+' end'

          ????????????????? when xtype in (175)

          ?????????????????????? then 'case when '+ name +' is null then ''NULL'' else '+''''''''' + ' + 'cast(replace('+ name+','''''''','''''''''''') as Char(' + cast(length as varchar)? + '))+'''''''''+' end'

          ????????????????? when xtype in (239)

          ?????????????????????? then 'case when '+ name +' is null then ''NULL'' else '+'''N'''''' + ' + 'cast(replace('+ name+','''''''','''''''''''') as Char(' + cast(length as varchar)? + '))+'''''''''+' end'

          ????????????????? else '''NULL'''

          ??????????????? end as Cols,name

          ?????????? from syscolumns?

          ????????? where id = object_id(@tablename)

          ??????? ) T

          ? set @sql ='select ''INSERT INTO ['+ @tablename + ']' + left(@sql,len(@sql)-1)+') ' + left(@sqlValues,len(@sqlValues)-4) + ')'' from '+@tablename

          ? --print @sql

          ? exec (@sql)

          end

          ?

          GO

          ?

          ?

          ?

          -- ======================================================

          --根據表中數據生成insert語句的存儲過程

          --建立存儲過程,執行 proc_insert 表名

          --感謝Sky_blue

          -- ======================================================

          ?

          CREATE proc proc_insert (@tablename varchar(256))

          as

          begin

          ?????? set nocount on

          ?????? declare @sqlstr varchar(4000)

          ?????? declare @sqlstr1 varchar(4000)

          ?????? declare @sqlstr2 varchar(4000)

          ?????? select @sqlstr='select ''insert '+@tablename

          ?????? select @sqlstr1=''

          ?????? select @sqlstr2=' ('

          ?????? select @sqlstr1= ' values ( ''+'

          ?????? select @sqlstr1=@sqlstr1+col+'+'',''+' ,@sqlstr2=@sqlstr2+name +',' from (select case

          --???? when a.xtype =173 then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar('+convert(varchar(4),a.length*2+2)+'),'+a.name +')'+' end'

          ?????? when a.xtype =104 then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar(1),'+a.name +')'+' end'

          ?????? when a.xtype =175 then 'case when '+a.name+' is null then ''NULL'' else '+'''''''''+'+'replace('+a.name+','''''''','''''''''''')' + '+'''''''''+' end'

          ?????? when a.xtype =61? then 'case when '+a.name+' is null then ''NULL'' else '+'''''''''+'+'convert(varchar(23),'+a.name +',121)'+ '+'''''''''+' end'

          ?????? when a.xtype =106 then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar('+convert(varchar(4),a.xprec+2)+'),'+a.name +')'+' end'

          ?????? when a.xtype =62? then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar(23),'+a.name +',2)'+' end'

          ?????? when a.xtype =56? then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar(11),'+a.name +')'+' end'

          ?????? when a.xtype =60? then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar(22),'+a.name +')'+' end'

          ?????? when a.xtype =239 then 'case when '+a.name+' is null then ''NULL'' else '+'''''''''+'+'replace('+a.name+','''''''','''''''''''')' + '+'''''''''+' end'

          ?????? when a.xtype =108 then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar('+convert(varchar(4),a.xprec+2)+'),'+a.name +')'+' end'

          ?????? when a.xtype =231 then 'case when '+a.name+' is null then ''NULL'' else '+'''''''''+'+'replace('+a.name+','''''''','''''''''''')' + '+'''''''''+' end'

          ?????? when a.xtype =59? then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar(23),'+a.name +',2)'+' end'

          ?????? when a.xtype =58? then 'case when '+a.name+' is null then ''NULL'' else '+'''''''''+'+'convert(varchar(23),'+a.name +',121)'+ '+'''''''''+' end'

          ?????? when a.xtype =52? then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar(12),'+a.name +')'+' end'

          ?????? when a.xtype =122 then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar(22),'+a.name +')'+' end'

          ?????? when a.xtype =48? then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar(6),'+a.name +')'+' end'

          --???? when a.xtype =165 then 'case when '+a.name+' is null then ''NULL'' else '+'convert(varchar('+convert(varchar(4),a.length*2+2)+'),'+a.name +')'+' end'

          ?????? when a.xtype =167 then 'case when '+a.name+' is null then ''NULL'' else '+'''''''''+'+'replace('+a.name+','''''''','''''''''''')' + '+'''''''''+' end'

          ?????? else '''NULL'''

          ?????? end as col,a.colid,a.name

          ?????? from syscolumns a where a.id = object_id(@tablename) and a.xtype <>189 and a.xtype <>34 and a.xtype <>35 and? a.xtype <>36

          ?????? )t order by colid

          ??????

          ?????? select @sqlstr=@sqlstr+left(@sqlstr2,len(@sqlstr2)-1)+') '+left(@sqlstr1,len(@sqlstr1)-3)+')'' from '+@tablename

          --? print @sqlstr

          ?????? exec( @sqlstr)

          ?????? set nocount off

          end

          GO

          posted @ 2006-08-07 12:05 nbt 閱讀(314) | 評論 (0)編輯 收藏

          Transact SQL 常用語句以及函數簡易說明(含示例)

               摘要: Transact SQL?? 語?句?功?能? ========================================================================    -- 數據操作?  ...  閱讀全文

          posted @ 2006-08-07 11:58 nbt 閱讀(435) | 評論 (0)編輯 收藏

          整理了一些t-sql技巧(轉自csdn)

               摘要: 一、?只復制一個表結構,不復制數據 ? select ? top ? 0 ? * ...  閱讀全文

          posted @ 2006-08-07 11:51 nbt 閱讀(548) | 評論 (0)編輯 收藏

          數據庫設計方法、規范與技巧(轉)

          一、數據庫設計過程
            數據庫技術是信息資源管理最有效的手段。數據庫設計是指對于一個給定的應用環境,構造最優的數據庫模式,建立數據庫及其應用系統,有效存儲數據,滿足用戶信息要求和處理要求。
            數據庫設計中需求分析階段綜合各個用戶的應用需求(現實世界的需求),在概念設計階段形成獨立于機器特點、獨立于各個DBMS產品的概念模式(信息世界模型),用E-R圖來描述。在邏輯設計階段將E-R圖轉換成具體的數據庫產品支持的數據模型如關系模型,形成數據庫邏輯模式。然后根據用戶處理的要求,安全性的考慮,在基本表的基礎上再建立必要的視圖(VIEW)形成數據的外模式。在物理設計階段根據DBMS特點和處理的需要,進行物理存儲安排,設計索引,形成數據庫內模式。
            1. 需求分析階段
            需求收集和分析,結果得到數據字典描述的數據需求(和數據流圖描述的處理需求)。
            需求分析的重點是調查、收集與分析用戶在數據管理中的信息要求、處理要求、安全性與完整性要求。
            需求分析的方法:調查組織機構情況、調查各部門的業務活動情況、協助用戶明確對新系統的各種要求、確定新系統的邊界。
            常用的調查方法有: 跟班作業、開調查會、請專人介紹、詢問、設計調查表請用戶填寫、查閱記錄。
            分析和表達用戶需求的方法主要包括自頂向下和自底向上兩類方法。自頂向下的結構化分析方法(Structured Analysis,簡稱SA方法)從最上層的系統組織機構入手,采用逐層分解的方式分析系統,并把每一層用數據流圖和數據字典描述。
            數據流圖表達了數據和處理過程的關系。系統中的數據則借助數據字典(Data Dictionary,簡稱DD)來描述。
            數據字典是各類數據描述的集合,它是關于數據庫中數據的描述,即元數據,而不是數據本身。數據字典通常包括數據項、數據結構、數據流、數據存儲和處理過程五個部分(至少應該包含每個字段的數據類型和在每個表內的主外鍵)。
            數據項描述={數據項名,數據項含義說明,別名,數據類型,長度,
                   取值范圍,取值含義,與其他數據項的邏輯關系}
            數據結構描述={數據結構名,含義說明,組成:{數據項或數據結構}}
            數據流描述={數據流名,說明,數據流來源,數據流去向,
                   組成:{數據結構},平均流量,高峰期流量}
            數據存儲描述={數據存儲名,說明,編號,流入的數據流,流出的數據流,   
                    組成:{數據結構},數據量,存取方式}
            處理過程描述={處理過程名,說明,輸入:{數據流},輸出:{數據流},
                    處理:{簡要說明}}
            2. 概念結構設計階段
            通過對用戶需求進行綜合、歸納與抽象,形成一個獨立于具體DBMS的概念模型,可以用E-R圖表示。
            概念模型用于信息世界的建模。概念模型不依賴于某一個DBMS支持的數據模型。概念模型可以轉換為計算機上某一DBMS支持的特定數據模型。
            概念模型特點:
            (1) 具有較強的語義表達能力,能夠方便、直接地表達應用中的各種語義知識。
            (2) 應該簡單、清晰、易于用戶理解,是用戶與數據庫設計人員之間進行交流的語言。
            概念模型設計的一種常用方法為IDEF1X方法,它就是把實體-聯系方法應用到語義數據模型中的一種語義模型化技術,用于建立系統信息模型。
            使用IDEF1X方法創建E-R模型的步驟如下所示:
            2.1 第零步——初始化工程
            這個階段的任務是從目的描述和范圍描述開始,確定建模目標,開發建模計劃,組織建模隊伍,收集源材料,制定約束和規范。收集源材料是這階段的重點。通過調查和觀察結果,業務流程,原有系統的輸入輸出,各種報表,收集原始數據,形成了基本數據資料表。
            2.2 第一步——定義實體
            實體集成員都有一個共同的特征和屬性集,可以從收集的源材料——基本數據資料表中直接或間接標識出大部分實體。根據源材料名字表中表示物的術語以及具有“代碼”結尾的術語,如客戶代碼、代理商代碼、產品代碼等將其名詞部分代表的實體標識出來,從而初步找出潛在的實體,形成初步實體表。
            2.3 第二步——定義聯系
            IDEF1X模型中只允許二元聯系,n元聯系必須定義為n個二元聯系。根據實際的業務需求和規則,使用實體聯系矩陣來標識實體間的二元關系,然后根據實際情況確定出連接關系的勢、關系名和說明,確定關系類型,是標識關系、非標識關系(強制的或可選的)還是非確定關系、分類關系。如果子實體的每個實例都需要通過和父實體的關系來標識,則為標識關系,否則為非標識關系。非標識關系中,如果每個子實體的實例都與而且只與一個父實體關聯,則為強制的,否則為非強制的。如果父實體與子實體代表的是同一現實對象,那么它們為分類關系。
            2.4 第三步——定義碼
            通過引入交叉實體除去上一階段產生的非確定關系,然后從非交叉實體和獨立實體開始標識侯選碼屬性,以便唯一識別每個實體的實例,再從侯選碼中確定主碼。為了確定主碼和關系的有效性,通過非空規則和非多值規則來保證,即一個實體實例的一個屬性不能是空值,也不能在同一個時刻有一個以上的值。找出誤認的確定關系,將實體進一步分解,最后構造出IDEF1X模型的鍵基視圖(KB圖)。
            2.5 第四步——定義屬性
            從源數據表中抽取說明性的名詞開發出屬性表,確定屬性的所有者。定義非主碼屬性,檢查屬性的非空及非多值規則。此外,還要檢查完全依賴函數規則和非傳遞依賴規則,保證一個非主碼屬性必須依賴于主碼、整個主碼、僅僅是主碼。以此得到了至少符合關系理論第三范式的改進的IDEF1X模型的全屬性視圖。
            2.6 第五步——定義其他對象和規則
            定義屬性的數據類型、長度、精度、非空、缺省值、約束規則等。定義觸發器、存儲過程、視圖、角色、同義詞、序列等對象信息。
            3. 邏輯結構設計階段
            將概念結構轉換為某個DBMS所支持的數據模型(例如關系模型),并對其進行優化。設計邏輯結構應該選擇最適于描述與表達相應概念結構的數據模型,然后選擇最合適的DBMS。
            將E-R圖轉換為關系模型實際上就是要將實體、實體的屬性和實體之間的聯系轉化為關系模式,這種轉換一般遵循如下原則:
            1)一個實體型轉換為一個關系模式。實體的屬性就是關系的屬性。實體的碼就是關系的碼。
            2)一個m:n聯系轉換為一個關系模式。與該聯系相連的各實體的碼以及聯系本身的屬性均轉換為關系的屬性。而關系的碼為各實體碼的組合。
            3)一個1:n聯系可以轉換為一個獨立的關系模式,也可以與n端對應的關系模式合并。如果轉換為一個獨立的關系模式,則與該聯系相連的各實體的碼以及聯系本身的屬性均轉換為關系的屬性,而關系的碼為n端實體的碼。
            4)一個1:1聯系可以轉換為一個獨立的關系模式,也可以與任意一端對應的關系模式合并。
            5)三個或三個以上實體間的一個多元聯系轉換為一個關系模式。與該多元聯系相連的各實體的碼以及聯系本身的屬性均轉換為關系的屬性。而關系的碼為各實體碼的組合。
            6)同一實體集的實體間的聯系,即自聯系,也可按上述1:1、1:n和m:n三種情況分別處理。
            7)具有相同碼的關系模式可合并。
            為了進一步提高數據庫應用系統的性能,通常以規范化理論為指導,還應該適當地修改、調整數據模型的結構,這就是數據模型的優化。確定數據依賴。消除冗余的聯系。確定各關系模式分別屬于第幾范式。確定是否要對它們進行合并或分解。一般來說將關系分解為3NF的標準,即:
            表內的每一個值都只能被表達一次。
            表內的每一行都應該被唯一的標識(有唯一鍵)。
            表內不應該存儲依賴于其他鍵的非鍵信息。
            4. 數據庫物理設計階段
            為邏輯數據模型選取一個最適合應用環境的物理結構(包括存儲結構和存取方法)。根據DBMS特點和處理的需要,進行物理存儲安排,設計索引,形成數據庫內模式。
            5. 數據庫實施階段
            運用DBMS提供的數據語言(例如SQL)及其宿主語言(例如C),根據邏輯設計和物理設計的結果建立數據庫,編制與調試應用程序,組織數據入庫,并進行試運行。 數據庫實施主要包括以下工作:用DDL定義數據庫結構、組織數據入庫 、編制與調試應用程序、數據庫試運行
            6. 數據庫運行和維護階段
            數據庫應用系統經過試運行后即可投入正式運行。在數據庫系統運行過程中必須不斷地對其進行評價、調整與修改。包括:數據庫的轉儲和恢復、數據庫的安全性、完整性控制、數據庫性能的監督、分析和改進、數據庫的重組織和重構造。

            建模工具的使用
            為加快數據庫設計速度,目前有很多數據庫輔助工具(CASE工具),如Rational公司的Rational Rose,CA公司的Erwin和Bpwin,Sybase公司的PowerDesigner以及Oracle公司的Oracle Designer等。
            ERwin主要用來建立數據庫的概念模型和物理模型。它能用圖形化的方式,描述出實體、聯系及實體的屬性。ERwin支持IDEF1X方法。通過使用ERwin建模工具自動生成、更改和分析IDEF1X模型,不僅能得到優秀的業務功能和數據需求模型,而且可以實現從IDEF1X模型到數據庫物理設計的轉變。ERwin工具繪制的模型對應于邏輯模型和物理模型兩種。在邏輯模型中,IDEF1X工具箱可以方便地用圖形化的方式構建和繪制實體聯系及實體的屬性。在物理模型中,ERwin可以定義對應的表、列,并可針對各種數據庫管理系統自動轉換為適當的類型。
            設計人員可根據需要選用相應的數據庫設計建模工具。例如需求分析完成之后,設計人員可以使用Erwin畫ER圖,將ER圖轉換為關系數據模型,生成數據庫結構;畫數據流圖,生成應用程序。
            二、數據庫設計技巧
            1. 設計數據庫之前(需求分析階段)
            1) 理解客戶需求,詢問用戶如何看待未來需求變化。讓客戶解釋其需求,而且隨著開發的繼續,還要經常詢問客戶保證其需求仍然在開發的目的之中。
            2) 了解企業業務可以在以后的開發階段節約大量的時間。
            3) 重視輸入輸出。
            在定義數據庫表和字段需求(輸入)時,首先應檢查現有的或者已經設計出的報表、查詢和視圖(輸出)以決定為了支持這些輸出哪些是必要的表和字段。
            舉例:假如客戶需要一個報表按照郵政編碼排序、分段和求和,你要保證其中包括了單獨的郵政編碼字段而不要把郵政編碼糅進地址字段里。
            4) 創建數據字典和ER 圖表
            ER 圖表和數據字典可以讓任何了解數據庫的人都明確如何從數據庫中獲得數據。ER圖對表明表之間關系很有用,而數據字典則說明了每個字段的用途以及任何可能存在的別名。對SQL 表達式的文檔化來說這是完全必要的。
            5) 定義標準的對象命名規范
            數據庫各種對象的命名必須規范。
            2. 表和字段的設計(數據庫邏輯設計)
            表設計原則
            1) 標準化和規范化
            數據的標準化有助于消除數據庫中的數據冗余。標準化有好幾種形式,但Third Normal Form(3NF)通常被認為在性能、擴展性和數據完整性方面達到了最好平衡。簡單來說,遵守3NF 標準的數據庫的表設計原則是:“One Fact in One Place”即某個表只包括其本身基本的屬性,當不是它們本身所具有的屬性時需進行分解。表之間的關系通過外鍵相連接。它具有以下特點:有一組表專門存放通過鍵連接起來的關聯數據。
            舉例:某個存放客戶及其有關定單的3NF 數據庫就可能有兩個表:Customer 和Order。Order 表不包含定單關聯客戶的任何信息,但表內

            會存放一個鍵值,該鍵指向Customer 表里包含該客戶信息的那一行。
            事實上,為了效率的緣故,對表不進行標準化有時也是必要的。
            2) 數據驅動
            采用數據驅動而非硬編碼的方式,許多策略變更和維護都會方便得多,大大增強系統的靈活性和擴展性。
            舉例,假如用戶界面要訪問外部數據源(文件、XML 文檔、其他數據庫等),不妨把相應的連接和路徑信息存儲在用戶界面支持表里。還有,如果用戶界面執行工作流之類的任務(發送郵件、打印信箋、修改記錄狀態等),那么產生工作流的數據也可以存放在數據庫里。角色權限管理也可以通過數據驅動來完成。事實上,如果過程是數據驅動的,你就可以把相當大的責任推給用戶,由用戶來維護自己的工作流過程。
            3) 考慮各種變化
            在設計數據庫的時候考慮到哪些數據字段將來可能會發生變更。
            舉例,姓氏就是如此(注意是西方人的姓氏,比如女性結婚后從夫姓等)。所以,在建立系統存儲客戶信息時,在單獨的一個數據表里存儲姓氏字段,而且還附加起始日和終止日等字段,這樣就可以跟蹤這一數據條目的變化。

            字段設計原則
            4) 每個表中都應該添加的3 個有用的字段
            ??dRecordCreationDate,在VB 下默認是Now(),而在SQL Server 下默認為GETDATE()
            ??sRecordCreator,在SQL Server 下默認為NOT NULL DEFAULT USER
            ??nRecordVersion,記錄的版本標記;有助于準確說明記錄中出現null 數據或者丟失數據的原因
            5) 對地址和電話采用多個字段
            描述街道地址就短短一行記錄是不夠的。Address_Line1、Address_Line2 和Address_Line3 可以提供更大的靈活性。還有,電話號碼和郵件地址最好擁有自己的數據表,其間具有自身的類型和標記類別。
            6) 使用角色實體定義屬于某類別的列
            在需要對屬于特定類別或者具有特定角色的事物做定義時,可以用角色實體來創建特定的時間關聯關系,從而可以實現自我文檔化。
            舉例:用PERSON 實體和PERSON_TYPE 實體來描述人員。比方說,當John Smith, Engineer 提升為John Smith, Director 乃至最后爬到John Smith, CIO 的高位,而所有你要做的不過是改變兩個表PERSON 和PERSON_TYPE 之間關系的鍵值,同時增加一個日期/時間字段來知道變化是何時發生的。這樣,你的PERSON_TYPE 表就包含了所有PERSON 的可能類型,比如Associate、Engineer、Director、CIO 或者CEO 等。還有個替代辦法就是改變PERSON 記錄來反映新頭銜的變化,不過這樣一來在時間上無法跟蹤個人所處位置的具體時間。
            7) 選擇數字類型和文本類型盡量充足
            在SQL 中使用smallint 和tinyint 類型要特別小心。比如,假如想看看月銷售總額,總額字段類型是smallint,那么,如果總額超過了$32,767 就不能進行計算操作了。
            而ID 類型的文本字段,比如客戶ID 或定單號等等都應該設置得比一般想象更大。假設客戶ID 為10 位數長。那你應該把數據庫表字段的長度設為12 或者13 個字符長。但這額外占據的空間卻無需將來重構整個數據庫就可以實現數據庫規模的增長了。
            8) 增加刪除標記字段
            在表中包含一個“刪除標記”字段,這樣就可以把行標記為刪除。在關系數據庫里不要單獨刪除某一行;最好采用清除數據程序而且要仔細維護索引整體性。
            3. 選擇鍵和索引(數據庫邏輯設計)
            鍵選擇原則:
            1) 鍵設計4 原則
            ??為關聯字段創建外鍵。
            ??所有的鍵都必須唯一。
            ??避免使用復合鍵。
            ??外鍵總是關聯唯一的鍵字段。
            2) 使用系統生成的主鍵
            設計數據庫的時候采用系統生成的鍵作為主鍵,那么實際控制了數據庫的索引完整性。這樣,數據庫和非人工機制就有效地控制了對存儲數據中每一行的訪問。采用系統生成鍵作為主鍵還有一個優點:當擁有一致的鍵結構時,找到邏輯缺陷很容易。
            3) 不要用用戶的鍵(不讓主鍵具有可更新性)
            在確定采用什么字段作為表的鍵的時候,可一定要小心用戶將要編輯的字段。通常的情況下不要選擇用戶可編輯的字段作為鍵。
            4) 可選鍵有時可做主鍵
            把可選鍵進一步用做主鍵,可以擁有建立強大索引的能力。

            索引使用原則:
            索引是從數據庫中獲取數據的最高效方式之一。95%的數據庫性能問題都可以采用索引技術得到解決。
            1) 邏輯主鍵使用唯一的成組索引,對系統鍵(作為存儲過程)采用唯一的非成組索引,對任何外鍵列采用非成組索引。考慮數據庫的空間有多大,表如何進行訪問,還有這些訪問是否主要用作讀寫。
            2) 大多數數據庫都索引自動創建的主鍵字段,但是可別忘了索引外鍵,它們也是經常使用的鍵,比如運行查詢顯示主表和所有關聯表的某條記錄就用得上。
            3) 不要索引memo/note 字段,不要索引大型字段(有很多字符),這樣作會讓索引占用太多的存儲空間。
            4) 不要索引常用的小型表
            不要為小型數據表設置任何鍵,假如它們經常有插入和刪除操作就更別這樣作了。對這些插入和刪除操作的索引維護可能比掃描表空間消耗更多的時間。

            4. 數據完整性設計(數據庫邏輯設計)
            1) 完整性實現機制:
            實體完整性:主鍵
            參照完整性:
            父表中刪除數據:級聯刪除;受限刪除;置空值
            父表中插入數據:受限插入;遞歸插入
            父表中更新數據:級聯更新;受限更新;置空值
            DBMS對參照完整性可以有兩種方法實現:外鍵實現機制(約束規則)和觸發器實現機制
            用戶定義完整性:
            NOT NULL;CHECK;觸發器
            2) 用約束而非商務規則強制數據完整性
            采用數據庫系統實現數據的完整性。這不但包括通過標準化實現的完整性而且還包括數據的功能性。在寫數據的時候還可以增加觸發器來保證數據的正確性。不要依賴于商務層保證數據完整性;它不能保證表之間(外鍵)的完整性所以不能強加于其他完整性規則之上。
            3) 強制指示完整性
            在有害數據進入數據庫之前將其剔除。激活數據庫系統的指示完整性特性。這樣可以保持數據的清潔而能迫使開發人員投入更多的時間處理錯誤條件。
            4) 使用查找控制數據完整性
            控制數據完整性的最佳方式就是限制用戶的選擇。只要有可能都應該提供給用戶一個清晰的價值列表供其選擇。這樣將減少鍵入代碼的錯誤和誤解同時提供數據的一致性。某些公共數據特別適合查找:國家代碼、狀態代碼等。
            5) 采用視圖
            為了在數據庫和應用程序代碼之間提供另一層抽象,可以為應用程序建立專門的視圖而不必非要應用程序直接訪問數據表。這樣做還等于在處理數據庫變更時給你提供了更多的自由。
            5. 其他設計技巧
            1) 避免使用觸發器
            觸發器的功能通常可以用其他方式實現。在調試程序時觸發器可能成為干擾。假如你確實需要采用觸發器,你最好集中對它文檔化。
            2) 使用常用英語(或者其他任何語言)而不要使用編碼
            在創建下拉菜單、列表、報表時最好按照英語名排序。假如需要編碼,可以在編碼旁附上用戶知道的英語。
            3) 保存常用信息
            讓一個表專門存放一般數據庫信息非常有用。在這個表里存放數據庫當前版本、最近檢查/修復(對Access)、關聯設計文檔的名稱、客戶等信息。這樣可以實現一種簡單機制跟蹤數據庫,當客戶抱怨他們的數據庫沒有達到希望的要求而與你聯系時,這樣做對非客戶機/服務器環境特別有用。
            4) 包含版本機制
            在數據庫中引入版本控制機制來確定使用中的數據庫的版本。時間一長,用戶的需求總是會改變的。最終可能會要求修改數據庫結構。把版本信息直接存放到數據庫中更為方便。
            5) 編制文檔
            對所有的快捷方式、命名規范、限制和函數都要編制文檔。
            采用給表、列、觸發器等加注釋的數據庫工具。對開發、支持和跟蹤修改非常有用。
            對數據庫文檔化,或者在數據庫自身的內部或者單獨建立文檔。這樣,當過了一年多時間后再回過頭來做第2 個版本,犯錯的機會將大大減少。
            6) 測試、測試、反復測試
            建立或者修訂數據庫之后,必須用用戶新輸入的數據測試數據字段。最重要的是,讓用戶進行測試并且同用戶一道保證選擇的數據類型滿足商業要求。測試需要在把新數據庫投入實際服務之前完成。
            7) 檢查設計
            在開發期間檢查數據庫設計的常用技術是通過其所支持的應用程序原型檢查數據庫。換句話說,針對每一種最終表達數據的原型應用,保證你檢查了數據模型并且查看如何取出數據。
            三、數據庫命名規范
            1. 實體(表)的命名
            1) 表以名詞或名詞短語命名,確定表名是采用復數還是單數形式,此外給表的別名定義簡單規則(比方說,如果表名是一個單詞,別名就取單詞的前4 個字母;如果表名是兩個單詞,就各取兩個單詞的前兩個字母組成4 個字母長的別名;如果表的名字由3 個單詞組成,從頭兩個單詞中各取一個然后從最后一個單詞中再取出兩個字母,結果還是組成4 字母長的別名,其余依次類推)
            對工作用表來說,表名可以加上前綴WORK_ 后面附上采用該表的應用程序的名字。在命名過程當中,根據語義拼湊縮寫即可。注意,由于ORCLE會將字段名稱統一成大寫或者小寫中的一種,所以要求加上下劃線。
            舉例:
            定義的縮寫 Sales: Sal 銷售;
            Order: Ord 訂單;
            Detail: Dtl 明細;
            則銷售訂單明細表命名為:Sal_Ord_Dtl;
            2) 如果表或者是字段的名稱僅有一個單詞,那么建議不使用縮寫,而是用完整的單詞。
            舉例:
            定義的縮寫 Material Ma 物品;
            物品表名為:Material, 而不是 Ma.
            但是字段物品編碼則是:Ma_ID;而不是Material_ID
            3) 所有的存儲值列表的表前面加上前綴Z
            目的是將這些值列表類排序在數據庫最后。
            4) 所有的冗余類的命名(主要是累計表)前面加上前綴X
            冗余類是為了提高數據庫效率,非規范化數據庫的時候加入的字段或者表
            5) 關聯類通過用下劃線連接兩個基本類之后,再加前綴R的方式命名,后面按照字母順序羅列兩個表名或者表名的縮寫。
            關聯表用于保存多對多關系。
            如果被關聯的表名大于10個字母,必須將原來的表名的進行縮寫。如果沒有其他原因,建議都使用縮寫。
            舉例:表Object與自身存在多對多的關系,則保存多對多關系的表命名為:R_Object;
            表 Depart和Employee;存在多對多的關系;則關聯表命名為R_Dept_Emp
            2. 屬性(列)的命名
            1) 采用有意義的列名,表內的列要針對鍵采用一整套設計規則。每一個表都將有一個自動ID作為主健,邏輯上的主健作為第一組候選主健來定義,如果是數據庫自動生成的編碼,統一命名為:ID;如果是自定義的邏輯上的編碼則用縮寫加“ID”的方法命名。如果鍵是數字類型,你可以用_NO 作為后綴;如果是字符類型則可以采用_CODE 后綴。對列名應該采用標準的前綴和后綴。
            舉例:銷售訂單的編號字段命名:Sal_Ord_ID;如果還存在一個數據庫生成的自動編號,則命名為:ID。
            2) 所有的屬性加上有關類型的后綴,注意,如果還需要其它的后綴,都放在類型后綴之前。
            注: 數據類型是文本的字段,類型后綴TX可以不寫。有些類型比較明顯的字段,可以不寫類型后綴。
            3) 采用前綴命名
            給每個表的列名都采用統一的前綴,那么在編寫SQL表達式的時候會得到大大的簡化。這樣做也確實有缺點,比如破壞了自動表連接工具的作用,后者把公共列名同某些數據庫聯系起來。
            3. 視圖的命名
            1) 視圖以V作為前綴,其他命名規則和表的命名類似;
            2) 命名應盡量體現各視圖的功能。
            4. 觸發器的命名
            觸發器以TR作為前綴,觸發器名為相應的表名加上后綴,Insert觸發器加"_I",Delete觸發器加"_D",Update觸發器加"_U",如:

            TR_Customer_I,TR_Customer_D,TR_Customer_U。
            5. 存儲過程名
            存儲過程應以"UP_"開頭,和系統的存儲過程區分,后續部分主要以動賓形式構成,并用下劃線分割各個組成部分。如增加代理商的帳戶的存儲過程為"UP_Ins_Agent_Account"。
            6. 變量名
            變量名采用小寫,若屬于詞組形式,用下劃線分隔每個單詞,如@my_err_no。
            7. 命名中其他注意事項
            1) 以上命名都不得超過30個字符的系統限制。變量名的長度限制為29(不包括標識字符@)。
            2) 數據對象、變量的命名都采用英文字符,禁止使用中文命名。絕對不要在對象名的字符之間留空格。
            3) 小心保留詞,要保證你的字段名沒有和保留詞、數據庫系統或者常用訪問方法沖突
            5) 保持字段名和類型的一致性,在命名字段并為其指定數據類型的時候一定要保證一致性。假如數據類型在一個表里是整數,那在另一個表里可就別變成字符型了。

          posted @ 2006-08-07 11:46 nbt 閱讀(328) | 評論 (0)編輯 收藏

          PowerDesigner設計數據庫經驗

               摘要: (轉載自--http://www.cnblogs.com/qiubole/articles/116152.html) 采用 PowerDesigner 設計數據庫 ...  閱讀全文

          posted @ 2006-08-07 11:42 nbt 閱讀(1889) | 評論 (1)編輯 收藏

          僅列出標題
          共9頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 
          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導航

          統計

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          相冊

          收藏夾

          Java技術網站

          友情鏈接

          國內一些開源網站

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 和静县| 雷山县| 墨江| 南皮县| 芒康县| 会同县| 三穗县| 禄劝| 温泉县| 肃北| 永城市| 林周县| 镇原县| 乌鲁木齐县| 乌拉特中旗| 通州区| 龙州县| 延津县| 衡山县| 浦江县| 兴山县| 崇义县| 新干县| 图木舒克市| 南郑县| 醴陵市| 盐亭县| 益阳市| 青铜峡市| 日照市| 宜城市| 亳州市| 蓬溪县| 江北区| 织金县| 威信县| 乌鲁木齐县| 镇赉县| 丘北县| 寿宁县| 扬州市|