亚洲国产欧美一区二区三区,亚洲精品无码久久久久APP,亚洲天堂男人天堂http://m.tkk7.com/WshmAndLily/category/12010.htmlzh-cnThu, 10 Jan 2008 08:38:18 GMTThu, 10 Jan 2008 08:38:18 GMT60mysql項目sql schemahttp://m.tkk7.com/WshmAndLily/articles/173440.htmlsemovysemovyMon, 07 Jan 2008 12:08:00 GMThttp://m.tkk7.com/WshmAndLily/articles/173440.htmlhttp://m.tkk7.com/WshmAndLily/comments/173440.htmlhttp://m.tkk7.com/WshmAndLily/articles/173440.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/173440.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/173440.html###########################################
#### teckotooling database schema #########
###########################################

set names 'gbk';
drop database if exists teckotooling;
create database teckotooling
 character set utf8
 collate utf8_general_ci;
use teckotooling;
#頁面表
create table page
(
 page_id int(11) not null primary key auto_increment,
 page_name varchar(12) not null unique key,
 title_en varchar(128) default '',
 title_cn varchar(128) default '',
 title_hk varchar(128) default '',
 keyword_en varchar(128) default '',
 keyword_cn varchar(128) default '',
 keyword_hk varchar(128) default '', 
 title_content_en varchar(64) default '',
 title_content_cn varchar(64) default '',
 title_content_hk varchar(64) default '',
 content_en text default '',
 content_cn text default '',
 content_hk text default '', 
 readTimes int(11) default 0
)engine=innodb default charset=utf8;
#類別系列類
create table category
(
 category_id int(11) not null primary key auto_increment,
 categoryName_en varchar(64) not null unique key,
 categoryName_cn varchar(64) not null unique key,
 categoryName_hk varchar(64) not null unique key,
 description_en text default '',
 description_cn text default '',
 description_hk text default '',
 img varchar(32)
)engine=innodb default charset=utf8;
#項目表
create table item
(
 item_id int(11) not null primary key auto_increment,
 item_no varchar(6) not null unique key,
 category_id int(11) not null ,
 itemName_en varchar(64) not null unique key,
 itemName_cn varchar(64) not null unique key,
 itemName_hk varchar(64) not null unique key,
 img varchar(64),
 publishedDt timestamp,
 lastOne char(1) default 'n',
 visible char(1) default 'y',
 readTimes int(11) 
)engine=innodb default charset=utf8;
#基本文本屬性表
create table basicInfoText
(
 id int(11) not null primary key auto_increment,
 item_id int(11) not null,
 propertyName_en varchar(128) not null,
 propertyName_cn varchar(128) not null,
 propertyName_hk varchar(128) not null,
 propertyValue_en varchar(256) default '',
 propertyValue_cn varchar(256) default '',
 propertyValue_hk varchar(256) default '',
 unit_en varchar(32) default '',
 unit_cn varchar(32) default '',
 unit_hk varchar(32) default '',
 visible char(1) default 'y'
)engine=innodb default charset=utf8;
#基本圖片屬性表
create table basicInfoImg
(
 id int(11) not null primary key auto_increment,
 item_id int(11) not null ,
 imgName_en varchar(64),
 imgName_cn varchar(64),
 imgName_hk varchar(64),
 imgUrl varchar(64),
 visible char(1) default 'y'
)engine=innodb default charset=utf8;
#基本圖片屬性表
create table basicInfoDoc
(
 id int(11) not null primary key auto_increment,
 item_id int(11) not null ,
 docName_en varchar(128),
 docName_cn varchar(128),
 docName_hk varchar(128),
 docUrl varchar(64),
 size varchar(16) default '',
 contentType varchar(32) default '',
 readTimes int(11),
 enable char(1) default 'y',
 password varchar(32),
 visible char(1) default 'y'
)engine=innodb default charset=utf8;
#詳細(xì)屬性表
create table advancedInfo
(
 id int(11) not null primary key auto_increment,
 item_id int(11) not null ,
 content_en longText,
 content_cn longText,
 content_hk longText,
 visible char(1) default 'y'
)engine=innodb default charset=utf8;
#評論表
create table comment
(
 id int(11) not null primary key auto_increment,
 item_id int(11) not null ,
 commenter varchar(32) not null,
 dateTime timestamp,
 content longText default '',
 visible char(1) default 'y'
)engine=innodb default charset=utf8;
#留言表
create table leadWord
(
 id int(11) not null primary key auto_increment,
 leadWorder varchar(32) not null,
 dateTime timestamp,
 content longText default '',
 visible char(1) default 'y'
)engine=innodb default charset=utf8;
#創(chuàng)建其它設(shè)置表
create table otherConfig
(
 id int(11) not null primary key,
 enablePress char(1) default 'y',
 isImagePress char(1) default 'y',
 textPress varchar(32) default '',
 imagePress varchar(32) default '',
 userFaceStyle varchar(32) default '',
 afficheEn longText default '',
 afficheCn longText default '',
 afficheHk longText default ''  
);
#用戶表
create table user
(
 user_id int(11) not null primary key auto_increment,
 user_name varchar(32) not null,
 password varchar(32),
 ENABLED tinyint(1) not null default 0
)engine=innodb default charset=utf8;
#用戶權(quán)限表連接表
create table user_auth
(
 user_id int(11) not null,
 auth_id int(11) not null,
 primary key(user_id,auth_id)
)engine=innodb default charset=utf8;
#創(chuàng)建權(quán)限表
create table authority
(
 auth_id int(11) not null primary key auto_increment,
 authority varchar(255) not null,
 auth_type varchar(32) not null,
 protected_res varchar(128) not null,
 display varchar(64) not null,
 note varchar(64) default null
) engine=innodb default charset=utf8;

#參照完整性

#項目參照類別
alter table item
add  index  index_cat(category_id),
add constraint fk_item_category foreign key (category_id) references  category(category_id) on update cascade  on delete cascade ;
#項目文本屬性參照項目
alter table basicInfoText
add  index  index_bI(item_id),
add constraint fk_basicInfoText_item foreign key (item_id) references  item(item_id) on update cascade  on delete cascade ;
#項目圖片屬性參照項目
alter table basicInfoImg
add  index  index_bI(item_id),
add constraint  fk_basicInfoImg_item foreign key (item_id) references  item(item_id) on update cascade  on delete cascade ;
#項目文檔屬性參照項目
alter table basicInfoDoc
add  index  index_bI(item_id),
add constraint fk_basicInfoDoc_item foreign key (item_id) references  item(item_id) on update cascade  on delete cascade ;
#項目詳細(xì)文本參照項目
alter table advancedInfo
add  index  index_bI(item_id),
add constraint fk_advancedInfo_item foreign key  (item_id) references  item(item_id) on update cascade  on  delete cascade ;
#項目詳細(xì)文本參照項目
alter table comment
add  index  index_cI(item_id),
add constraint fk_comment_item foreign key  (item_id) references  item(item_id) on update cascade  on  delete cascade ;
#權(quán)限連接表參照用戶表
alter table user_auth
add  index  index_user(user_id),
add constraint fk_user_auth_user foreign key  (user_id) references  user(user_id) on update cascade  on  delete cascade ;
#初始化表

#用戶表
insert into user values(1,'admin','21232f297a57a5a743894a0e4a801fc3',1);
#頁面表
insert into page
 values(1,'home','home','home','home','home','home','home','home','home','home','home','home','home',0),
 (2,'about','about','about','about','about','about','about','about','about','about','about','about','about',0),
 (3,'product','product','product','product','product','product','product','product','product','product','product','product','product',0),
 (4,'services','services','services','services','services','services','services','services','services','services','services','services','services',0),
 (5,'contactUs','contactUs','contactUs','contactUs','contactUs','contactUs','contactUs','contactUs','contactUs','contactUs','contactUs','contactUs','contactUs',0);
#其它設(shè)置
insert into otherConfig values(1,'y','y','semovy@gmail.com','logo.gif','blue.css','affiche here...','公告在此……','公告在此……');
#初始資源鑒定表
INSERT INTO `authority` (`AUTH_ID`, `AUTHORITY`, `AUTH_TYPE`, `PROTECTED_RES`, `DISPLAY`, `NOTE`) VALUES
  #項目資源保護(hù)鑒定 
  (1,'AUTH_FUNC_ItemManager.saveItem','FUNCTION','com.semovy.service.IItemService.saveItem','創(chuàng)建項目',NULL),
  (2,'AUTH_FUNC_ItemManager.updateItem','FUNCTION','com.semovy.service.IItemService.updateItem','更新項目',NULL),
  (3,'AUTH_FUNC_ItemManager.deleteItemById','FUNCTION','com.semovy.service.IItemService.deleteItemById','刪除項目',NULL),
  (4,'AUTH_FUNC_ItemManager.outPutXMLItem','FUNCTION','com.semovy.service.IItemService.outPutXMLItem','訪問項目管理',NULL),
  #頁面資源
  (5,'AUTH_FUNC_PageManager.updatePage','FUNCTION','com.semovy.service.IPageService.updatePage','修改頁面',NULL),
  (6,'AUTH_FUNC_PageManager.outPutPageXML','FUNCTION','com.semovy.service.IPageService.outPutPageXML','訪問管理頁面',NULL),
  #其它管理
  (7,'AUTH_FUNC_OtherconfigManager.updateOtherconfig','FUNCTION','com.semovy.service.IOtherconfigService.updateOtherconfig','修改其它管理',NULL),
  (8,'AUTH_FUNC_OtherconfigManager.outPutOtherconfigXML','FUNCTION','com.semovy.service.IOtherconfigService.outPutOtherconfigXML','訪問其它管理',NULL),
  #用戶管理
  (9,'AUTH_FUNC_UserManager.updateUser','FUNCTION','com.semovy.service.IUserService.updateUser','修改用戶',NULL),
  (10,'AUTH_FUNC_UserManager.outPutUsersListXML','FUNCTION','com.semovy.service.IUserService.outPutUsersListXML','訪問用戶管理',NULL),
  #留言管理
  (11,'AUTH_FUNC_LeadwordManager.updateUser','FUNCTION','com.semovy.service.ILeadwordService.updateLeadword','修改留言',NULL),
  (12,'AUTH_FUNC_LeadwordManager.outPutUsersListXML','FUNCTION','com.semovy.service.ILeadwordService.deleteLeadwordById','刪除一條留言',NULL), 
  (13,'AUTH_FUNC_LeadwordManager.getLeadWordsOfPageByCriteria','FUNCTION','com.semovy.service.ILeadwordService.getLeadWordsOfPageByCriteria','獲取分頁留言',NULL),
  (14,'AUTH_FUNC_LeadwordManager.outPutXMLLeadword','FUNCTION','com.semovy.service.ILeadwordService.outPutXMLLeadword','訪問留言管理',NULL),   
  #評論管理
  (15,'AUTH_FUNC_CommentManager.updateComment','FUNCTION','com.semovy.service.ICommentService.updateComment','修改評論',NULL),
  (16,'AUTH_FUNC_CommentManager.deleteCommentById','FUNCTION','com.semovy.service.ICommentService.deleteCommentById','刪除一條評論',NULL), 
  (17,'AUTH_FUNC_CommentManager.outPutXMLComment','FUNCTION','com.semovy.service.ICommentService.outPutXMLComment','訪問評論管理',NULL),
  #項目基本文本管理
  (18,'AUTH_FUNC_BasicinfotextManager.getBasicinfotextById','FUNCTION','com.semovy.service.IBasicinfotextService.getBasicinfotextById','獲取一個項目基本文本屬性',NULL),
  (19,'AUTH_FUNC_BasicinfotextManager.saveBasicinfotext','FUNCTION','com.semovy.service.IBasicinfotextService.saveBasicinfotext','保存項目基本文本屬性',NULL), 
  (20,'AUTH_FUNC_BasicinfotextManager.deleteBasicinfotextById','FUNCTION','com.semovy.service.IBasicinfotextService.deleteBasicinfotextById','刪除項目基本文本屬性',NULL),
  #(21,'AUTH_FUNC_BasicinfotextManager.outPutLocaleUnitXML','FUNCTION','com.semovy.service.IBasicinfotextService.outPutLocaleUnitXML','訪問基本文本屬性單位',NULL),
  (22,'AUTH_FUNC_BasicinfotextManager.outPutBasicinfotextXMLOfItem','FUNCTION','com.semovy.service.IBasicinfotextService.outPutBasicinfotextXMLOfItem','訪問基本文本屬性管理',NULL),   
  #項目基本圖片管理
  (23,'AUTH_FUNC_BasicinfoimgManager.getBasicinfoimgById','FUNCTION','com.semovy.service.IBasicinfoimgService.getBasicinfoimgById','獲取一個項目基本圖片屬性',NULL),
  (24,'AUTH_FUNC_BasicinfoimgManager.saveBasicinfoimg','FUNCTION','com.semovy.service.IBasicinfoimgService.saveBasicinfoimg','保存項目基本圖片屬性',NULL), 
  (25,'AUTH_FUNC_BasicinfoimgManager.updateBasicinfoimg','FUNCTION','com.semovy.service.IBasicinfoimgService.updateBasicinfoimg','修改項目基本圖片屬性',NULL),
  (26,'AUTH_FUNC_BasicinfoimgManager.deleteBasicinfoimgById','FUNCTION','com.semovy.service.IBasicinfoimgService.deleteBasicinfoimgById','刪除基本圖片屬性',NULL),
  (27,'AUTH_FUNC_BasicinfoimgManager.outputBasicinfoimgXML','FUNCTION','com.semovy.service.IBasicinfoimgService.outputBasicinfoimgXML','訪問基本圖片屬性管理',NULL),     
  #項目基本文檔管理
  #(28,'AUTH_FUNC_BasicinfodocManager.getBasicinfodocById','FUNCTION','com.semovy.service.IBasicinfodocService.getBasicinfodocById','獲取一個項目基本文檔屬性',NULL),
  (29,'AUTH_FUNC_BasicinfodocManager.saveBasicinfodoc','FUNCTION','com.semovy.service.IBasicinfodocService.saveBasicinfodoc','保存項目基本文檔屬性',NULL), 
  (30,'AUTH_FUNC_BasicinfodocManager.updateBasicinfodoc','FUNCTION','com.semovy.service.IBasicinfodocService.updateBasicinfodoc','修改項目基本文檔屬性',NULL),
  (31,'AUTH_FUNC_BasicinfodocManager.deleteBasicinfodocById','FUNCTION','com.semovy.service.IBasicinfodocService.deleteBasicinfodocById','刪除基本文檔屬性',NULL),
  (32,'AUTH_FUNC_BasicinfodocManager.outputBasicinfodocXML','FUNCTION','com.semovy.service.IBasicinfodocService.outputBasicinfodocXML','訪問基本圖片文檔管理',NULL),       
  #項目高級文本管理
  (33,'AUTH_FUNC_AdvancedinfoManager.getAdvancedinfoById','FUNCTION','com.semovy.service.IAdvancedinfoService.getAdvancedinfoById','獲取一個項目高級文本屬性',NULL),
  (34,'AUTH_FUNC_AdvancedinfoManager.saveAdvancedinfo','FUNCTION','com.semovy.service.IAdvancedinfoService.saveAdvancedinfo','保存項目項目高級文本',NULL), 
  (35,'AUTH_FUNC_AdvancedinfoManager.updateAdvancedinfo','FUNCTION','com.semovy.service.IAdvancedinfoService.updateAdvancedinfo','修改項目項目高級文本',NULL),
  (36,'AUTH_FUNC_AdvancedinfoManager.deleteAdvancedinfoById','FUNCTION','com.semovy.service.IAdvancedinfoService.deleteAdvancedinfoById','刪除項目高級文本',NULL), 
  #項目類別管理
  (37,'AUTH_FUNC_CategoryManager.saveCategory','FUNCTION','com.semovy.service.ICategoryService.saveCategory','保存項目類別',NULL),
  (38,'AUTH_FUNC_CategoryManager.updateCategory','FUNCTION','com.semovy.service.ICategoryService.updateCategory','修改項目類別',NULL), 
  (39,'AUTH_FUNC_CategoryManager.deleteCategoryById','FUNCTION','com.semovy.service.ICategoryService.deleteCategoryById','刪除項目類別',NULL),
  (40,'AUTH_FUNC_CategoryManager.outputCategoriesXML','FUNCTION','com.semovy.service.ICategoryService.outputCategoriesXML','訪問管理項目類別',NULL);   
#初始化user_auth表
insert into user_auth values
   (1,1),
   (1,2),
   (1,3), 
   (1,4),
   (1,5),
   (1,6), 
   (1,7),
   (1,8),
   (1,9), 
   (1,10),
   (1,11),
   (1,12), 
   (1,13),
   (1,14),
   (1,15), 
   (1,16),
   (1,17),
   (1,18), 
   (1,19),
   (1,20),
   (1,21), 
   (1,22),
   (1,23),
   (1,24), 
   (1,25),
   (1,26),
   (1,27), 
   (1,28),
   (1,29),
   (1,30),
   (1,31), 
   (1,32),
   (1,33),
   (1,34), 
   (1,35),
   (1,36),
   (1,37), 
   (1,38),
   (1,39),
   (1,40);                                    



semovy 2008-01-07 20:08 發(fā)表評論
]]>
mysql 命令http://m.tkk7.com/WshmAndLily/articles/173438.htmlsemovysemovyMon, 07 Jan 2008 12:02:00 GMThttp://m.tkk7.com/WshmAndLily/articles/173438.htmlhttp://m.tkk7.com/WshmAndLily/comments/173438.htmlhttp://m.tkk7.com/WshmAndLily/articles/173438.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/173438.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/173438.html
desc table顯示表的結(jié)構(gòu)

show tables顯示當(dāng)前數(shù)據(jù)庫的所有表

semovy 2008-01-07 20:02 發(fā)表評論
]]>
java備份mysqlhttp://m.tkk7.com/WshmAndLily/articles/135022.htmlsemovysemovyTue, 07 Aug 2007 09:50:00 GMThttp://m.tkk7.com/WshmAndLily/articles/135022.htmlhttp://m.tkk7.com/WshmAndLily/comments/135022.htmlhttp://m.tkk7.com/WshmAndLily/articles/135022.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/135022.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/135022.html完整代碼:
    /**
     * @param args
     */
    public static void main(String[] args) {
        /*
         * 備份和導(dǎo)入是一個互逆的過程。
         * 備份:程序調(diào)用mysql的備份命令,讀出控制臺輸入流信息,寫入.sql文件;
         * 導(dǎo)入:程序調(diào)用mysql的導(dǎo)入命令,把從.sql文件中讀出的信息寫入控制臺的輸出流
         * 注意:此時定向符">"和"<"是不能用的
         */
        backup();
        load();
    }

    /**
     * 備份檢驗一個sql文件是否可以做導(dǎo)入文件用的一個判斷方法:把該sql文件分別用記事本和ultra
     * edit打開,如果看到的中文均正常沒有亂碼,則可以用來做導(dǎo)入的源文件(不管sql文件的編碼格式如何,也不管db的編碼格式如何)
     */
    public static void backup() {
        try {
            Runtime rt = Runtime.getRuntime();

            // 調(diào)用 mysql 的 cmd:
            Process child = rt
                    .exec("mysqldump -u root --set-charset=utf8 bjse act_obj");// 設(shè)置導(dǎo)出編碼為utf8。這里必須是utf8
           
            // 把進(jìn)程執(zhí)行中的控制臺輸出信息寫入.sql文件,即生成了備份文件。注:如果不對控制臺信息進(jìn)行讀出,則會導(dǎo)致進(jìn)程堵塞無法運行
            InputStream in = child.getInputStream();// 控制臺的輸出信息作為輸入流
                       
            InputStreamReader xx = new InputStreamReader(in, "utf8");// 設(shè)置輸出流編碼為utf8。這里必須是utf8,否則從流中讀入的是亂碼
           
            String inStr;
            StringBuffer sb = new StringBuffer("");
            String outStr;
            // 組合控制臺輸出信息字符串
            BufferedReader br = new BufferedReader(xx);
            while ((inStr = br.readLine()) != null) {
                sb.append(inStr + "\r\n");
            }
            outStr = sb.toString();
           
            // 要用來做導(dǎo)入用的sql目標(biāo)文件:
            FileOutputStream fout = new FileOutputStream(
                    "e:/mysql-5.0.27-win32/bin/bjse22.sql");
            OutputStreamWriter writer = new OutputStreamWriter(fout, "utf8");
            writer.write(outStr);
            // 注:這里如果用緩沖方式寫入文件的話,會導(dǎo)致中文亂碼,用flush()方法則可以避免
            writer.flush();

            // 別忘記關(guān)閉輸入輸出流
            in.close();
            xx.close();
            br.close();
            writer.close();
            fout.close();

            System.out.println("/* Output OK! */");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 導(dǎo)入
     *
     */
    public static void load() {
        try {
            String fPath = "e:/mysql-5.0.27-win32/bin/bjse22.sql";
            Runtime rt = Runtime.getRuntime();

            // 調(diào)用 mysql 的 cmd:
            Process child = rt.exec("mysql -u root bjse ");
            OutputStream out = child.getOutputStream();//控制臺的輸入信息作為輸出流
            String inStr;
            StringBuffer sb = new StringBuffer("");
            String outStr;
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    new FileInputStream(fPath), "utf8"));
            while ((inStr = br.readLine()) != null) {
                sb.append(inStr + "\r\n");
            }
            outStr = sb.toString();

            OutputStreamWriter writer = new OutputStreamWriter(out, "utf8");
            writer.write(outStr);
            // 注:這里如果用緩沖方式寫入文件的話,會導(dǎo)致中文亂碼,用flush()方法則可以避免
            writer.flush();
            // 別忘記關(guān)閉輸入輸出流
            out.close();
            br.close();
            writer.close();

            System.out.println("/* Load OK! */");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }


semovy 2007-08-07 17:50 發(fā)表評論
]]>
mysql數(shù)據(jù)類型http://m.tkk7.com/WshmAndLily/articles/130973.htmlsemovysemovyWed, 18 Jul 2007 02:01:00 GMThttp://m.tkk7.com/WshmAndLily/articles/130973.htmlhttp://m.tkk7.com/WshmAndLily/comments/130973.htmlhttp://m.tkk7.com/WshmAndLily/articles/130973.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/130973.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/130973.html

數(shù)值類型

  MySQL 的數(shù)值數(shù)據(jù)類型可以大致劃分為兩個類別,一個是整數(shù),另一個是浮點數(shù)或小數(shù)。許多不同的子類型對這些類別中的每一個都是可用的,每個子類型支持不同大小的數(shù)據(jù),并且 MySQL 允許我們指定數(shù)值字段中的值是否有正負(fù)之分或者用零填補。

  表列出了各種數(shù)值類型以及它們的允許范圍和占用的內(nèi)存空間。

類型
大小
范圍(有符號)
范圍(無符號)
用途
TINYINT
1 字節(jié)
(-128,127)
(0,255)
小整數(shù)值
SMALLINT
2 字節(jié)
(-32 768,32 767)
(0,65 535)
大整數(shù)值
MEDIUMINT
3 字節(jié)
(-8 388 608,8 388 607)
(0,16 777 215)
大整數(shù)值
INT或INTEGER
4 字節(jié)
(-2 147 483 648,2 147 483 647)
(0,4 294 967 295)
大整數(shù)值
BIGINT
8 字節(jié)
(-9 233 372 036 854 775 808,9 223 372 036 854 775 807)
(0,18 446 744 073 709 551 615)
極大整數(shù)值
FLOAT
4 字節(jié)
(-3.402 823 466 E+38,1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38)
0,(1.175 494 351 E-38,3.402 823 466 E+38)
單精度
浮點數(shù)值
DOUBLE
8 字節(jié)
(1.797 693 134 862 315 7 E+308,2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)
0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308)
雙精度
浮點數(shù)值
DECIMAL
對DECIMAL(M,D) ,如果M>D,為M+2否則為D+2
依賴于M和D的值
依賴于M和D的值
小數(shù)值

 

INT 類型

  在 MySQL 中支持的 5 個主要整數(shù)類型是 TINYINT,SMALLINT,MEDIUMINT,INT 和 BIGINT。這些類型在很大程度上是相同的,只有它們存儲的值的大小是不相同的。

  MySQL 以一個可選的顯示寬度指示器的形式對 SQL 標(biāo)準(zhǔn)進(jìn)行擴(kuò)展,這樣當(dāng)從數(shù)據(jù)庫檢索一個值時,可以把這個值加長到指定的長度。例如,指定一個字段的類型為 INT(6),就可以保證所包含數(shù)字少于 6 個的值從數(shù)據(jù)庫中檢索出來時能夠自動地用空格填充。需要注意的是,使用一個寬度指示器不會影響字段的大小和它可以存儲的值的范圍。

  萬一我們需要對一個字段存儲一個超出許可范圍的數(shù)字,MySQL 會根據(jù)允許范圍最接近它的一端截短后再進(jìn)行存儲。還有一個比較特別的地方是,MySQL 會在不合規(guī)定的值插入表前自動修改為 0。

  UNSIGNED 修飾符規(guī)定字段只保存正值。因為不需要保存數(shù)字的正、負(fù)符號,可以在儲時節(jié)約一個“位”的空間。從而增大這個字段可以存儲的值的范圍。

  ZEROFILL 修飾符規(guī)定 0(不是空格)可以用來真補輸出的值。使用這個修飾符可以阻止 MySQL 數(shù)據(jù)庫存儲負(fù)值。

FLOAT、DOUBLE 和 DECIMAL 類型

  MySQL 支持的三個浮點類型是 FLOAT、DOUBLE 和 DECIMAL 類型。FLOAT 數(shù)值類型用于表示單精度浮點數(shù)值,而 DOUBLE 數(shù)值類型用于表示雙精度浮點數(shù)值。

  與整數(shù)一樣,這些類型也帶有附加參數(shù):一個顯示寬度指示器和一個小數(shù)點指示器。比如語句 FLOAT(7,3) 規(guī)定顯示的值不會超過 7 位數(shù)字,小數(shù)點后面帶有 3 位數(shù)字。

  對于小數(shù)點后面的位數(shù)超過允許范圍的值,MySQL 會自動將它四舍五入為最接近它的值,再插入它。

  DECIMAL 數(shù)據(jù)類型用于精度要求非常高的計算中,這種類型允許指定數(shù)值的精度和計數(shù)方法作為選擇參數(shù)。精度在這里指為這個值保存的有效數(shù)字的總個數(shù),而計數(shù)方法表示小數(shù)點后數(shù)字的位數(shù)。比如語句 DECIMAL(7,3) 規(guī)定了存儲的值不會超過 7 位數(shù)字,并且小數(shù)點后不超過 3 位。

  忽略 DECIMAL 數(shù)據(jù)類型的精度和計數(shù)方法修飾符將會使 MySQL 數(shù)據(jù)庫把所有標(biāo)識為這個數(shù)據(jù)類型的字段精度設(shè)置為 10,計算方法設(shè)置為 0。

  UNSIGNED 和 ZEROFILL 修飾符也可以被 FLOAT、DOUBLE 和 DECIMAL 數(shù)據(jù)類型使用。并且效果與 INT 數(shù)據(jù)類型相同。

字符串類型

  MySQL 提供了 8 個基本的字符串類型,可以存儲的范圍從簡單的一個字符到巨大的文本塊或二進(jìn)制字符串?dāng)?shù)據(jù)。

類型
大小
用途
CHAR
0-255字節(jié)
定長字符串
VARCHAR
0-255字節(jié)
變長字符串
TINYBLOB
0-255字節(jié)
不超過 255 個字符的二進(jìn)制字符串
TINYTEXT
0-255字節(jié)
短文本字符串
BLOB
0-65 535字節(jié)
二進(jìn)制形式的長文本數(shù)據(jù)
TEXT
0-65 535字節(jié)
長文本數(shù)據(jù)
MEDIUMBLOB
0-16 777 215字節(jié)
二進(jìn)制形式的中等長度文本數(shù)據(jù)
MEDIUMTEXT
0-16 777 215字節(jié)
中等長度文本數(shù)據(jù)
LOGNGBLOB
0-4 294 967 295字節(jié)
二進(jìn)制形式的極大文本數(shù)據(jù)
LONGTEXT
0-4 294 967 295字節(jié)
極大文本數(shù)據(jù)

CHAR 和 VARCHAR 類型

  CHAR 類型用于定長字符串,并且必須在圓括號內(nèi)用一個大小修飾符來定義。這個大小修飾符的范圍從 0-255。比指定長度大的值將被截短,而比指定長度小的值將會用空格作填補。

  CHAR 類型可以使用 BINARY 修飾符。當(dāng)用于比較運算時,這個修飾符使 CHAR 以二進(jìn)制方式參于運算,而不是以傳統(tǒng)的區(qū)分大小寫的方式。

  CHAR 類型的一個變體是 VARCHAR 類型。它是一種可變長度的字符串類型,并且也必須帶有一個范圍在 0-255 之間的指示器。CHAR 和 VARCHGAR 不同之處在于 MuSQL 數(shù)據(jù)庫處理這個指示器的方式:CHAR 把這個大小視為值的大小,不長度不足的情況下就用空格補足。而 VARCHAR 類型把它視為最大值并且只使用存儲字符串實際需要的長度(增加一個額外字節(jié)來存儲字符串本身的長度)來存儲值。所以短于指示器長度的 VARCHAR 類型不會被空格填補,但長于指示器的值仍然會被截短。

  因為 VARCHAR 類型可以根據(jù)實際內(nèi)容動態(tài)改變存儲值的長度,所以在不能確定字段需要多少字符時使用 VARCHAR 類型可以大大地節(jié)約磁盤空間、提高存儲效率。

  VARCHAR 類型在使用 BINARY 修飾符時與 CHAR 類型完全相同。

TEXT 和 BLOB 類型

  對于字段長度要求超過 255 個的情況下,MySQL 提供了 TEXT 和 BLOB 兩種類型。根據(jù)存儲數(shù)據(jù)的大小,它們都有不同的子類型。這些大型的數(shù)據(jù)用于存儲文本塊或圖像、聲音文件等二進(jìn)制數(shù)據(jù)類型。

  TEXT 和 BLOB 類型在分類和比較上存在區(qū)別。BLOB 類型區(qū)分大小寫,而 TEXT 不區(qū)分大小寫。大小修飾符不用于各種 BLOB 和 TEXT 子類型。比指定類型支持的最大范圍大的值將被自動截短。

 

日期和時間類型

  在處理日期和時間類型的值時,MySQL 帶有 5 個不同的數(shù)據(jù)類型可供選擇。它們可以被分成簡單的日期、時間類型,和混合日期、時間類型。根據(jù)要求的精度,子類型在每個分類型中都可以使用,并且 MySQL 帶有內(nèi)置功能可以把多樣化的輸入格式變?yōu)橐粋€標(biāo)準(zhǔn)格式。

類型
大小
(字節(jié))
范圍
格式
用途
DATE
3
1000-01-01/9999-12-31
YYYY-MM-DD
日期值
TIME
3
'-838:59:59'/'838:59:59'
HH:MM:SS
時間值或持續(xù)時間
YEAR
1
1901/2155
YYYY
年份值
DATETIME
8
1000-01-01 00:00:00/9999-12-31 23:59:59
YYYY-MM-DD HH:MM:SS
混合日期和時間值
TIMESTAMP
8
1970-01-01 00:00:00/2037 年某時
YYYYMMDD HHMMSS
混合日期和時間值,時間戳

DATE、TIME 和 TEAR 類型

  MySQL 用 DATE 和 TEAR 類型存儲簡單的日期值,使用 TIME 類型存儲時間值。這些類型可以描述為字符串或不帶分隔符的整數(shù)序列。如果描述為字符串,DATE 類型的值應(yīng)該使用連字號作為分隔符分開,而 TIME 類型的值應(yīng)該使用冒號作為分隔符分開。

  需要注意的是,沒有冒號分隔符的 TIME 類型值,將會被 MySQL 理解為持續(xù)的時間,而不是時間戳。

  MySQL 還對日期的年份中的兩個數(shù)字的值,或是 SQL 語句中為 TEAR 類型輸入的兩個數(shù)字進(jìn)行最大限度的通譯。因為所有 TEAR 類型的值必須用 4 個數(shù)字存儲。MySQL 試圖將 2 個數(shù)字的年份轉(zhuǎn)換為 4 個數(shù)字的值。把在 00-69 范圍內(nèi)的值轉(zhuǎn)換到 2000-2069 范圍內(nèi)。把 70-99 范圍內(nèi)的值轉(zhuǎn)換到 1970-1979 之內(nèi)。如果 MySQL 自動轉(zhuǎn)換后的值并不符合我們的需要,請輸入 4 個數(shù)字表示的年份。

DATEYIME 和 TIMESTAMP 類型

   除了日期和時間數(shù)據(jù)類型,MySQL 還支持 DATEYIME 和 TIMESTAMP 這兩種混合類型。它們可以把日期和時間作為單個的值進(jìn)行存儲。這兩種類型通常用于自動存儲包含當(dāng)前日期和時間的時間戳,并可在需要執(zhí)行大量數(shù)據(jù)庫事務(wù)和需要建立一個調(diào)試和審查用途的審計跟蹤的應(yīng)用程序中發(fā)揮良好作用。

  如果我們對 TIMESTAMP 類型的字段沒有明確賦值,或是被賦與了 null 值。MySQL 會自動使用系統(tǒng)當(dāng)前的日期和時間來填充它。

 

復(fù)合類型

  MySQL 還支持兩種復(fù)合數(shù)據(jù)類型 ENUM 和 SET,它們擴(kuò)展了 SQL 規(guī)范。雖然這些類型在技術(shù)上是字符串類型,但是可以被視為不同的數(shù)據(jù)類型。一個 ENUM 類型只允許從一個集合中取得一個值;而 SET 類型允許從一個集合中取得任意多個值。

 

ENUM 類型

  ENUM 類型因為只允許在集合中取得一個值,有點類似于單選項。在處理相互排拆的數(shù)據(jù)時容易讓人理解,比如人類的性別。ENUM 類型字段可以從集合中取得一個值或使用 null 值,除此之外的輸入將會使 MySQL 在這個字段中插入一個空字符串。另外如果插入值的大小寫與集合中值的大小寫不匹配,MySQL 會自動使用插入值的大小寫轉(zhuǎn)換成與集合中大小寫一致的值。

   ENUM 類型在系統(tǒng)內(nèi)部可以存儲為數(shù)字,并且從 1 開始用數(shù)字做索引。一個 ENUM 類型最多可以包含 65536 個元素,其中一個元素被 MySQL 保留,用來存儲錯誤信息,這個錯誤值用索引 0 或者一個空字符串表示。

  MySQL 認(rèn)為 ENUM 類型集合中出現(xiàn)的值是合法輸入,除此之外其它任何輸入都將失敗。這說明通過搜索包含空字符串或?qū)?yīng)數(shù)字索引為 0 的行就可以很容易地找到錯誤記錄的位置。

SET 類型

  SET 類型與 ENUM 類型相似但不相同。SET 類型可以從預(yù)定義的集合中取得任意數(shù)量的值。并且與 ENUM 類型相同的是任何試圖在 SET 類型字段中插入非預(yù)定義的值都會使 MySQL 插入一個空字符串。如果插入一個即有合法的元素又有非法的元素的記錄,MySQL 將會保留合法的元素,除去非法的元素。

  一個 SET 類型最多可以包含 64 項元素。在 SET 元素中值被存儲為一個分離的“位”序列,這些“位”表示與它相對應(yīng)的元素。“位”是創(chuàng)建有序元素集合的一種簡單而有效的方式。并且它還去除了重復(fù)的元素,所以 SET 類型中不可能包含兩個相同的元素。

  希望從 SET 類型字段中找出非法的記錄只需查找包含空字符串或二進(jìn)制值為 0 的行。



semovy 2007-07-18 10:01 發(fā)表評論
]]>
jsp 備份和還原 mysql 數(shù)據(jù)庫http://m.tkk7.com/WshmAndLily/articles/116807.htmlsemovysemovyFri, 11 May 2007 09:30:00 GMThttp://m.tkk7.com/WshmAndLily/articles/116807.htmlhttp://m.tkk7.com/WshmAndLily/comments/116807.htmlhttp://m.tkk7.com/WshmAndLily/articles/116807.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/116807.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/116807.htmljsp實現(xiàn)備份和還原mysql數(shù)據(jù)庫,請給出代碼實例,謝謝!
這個帖一定要頂 MSsql 的知道 mysql的不知道 MSsql備份語句 BACKUP DATABASE [數(shù)據(jù)庫名稱] TO DISK=存放路徑文件名 WITH Format(完全備份)還原用 RESTORE DATABASE [數(shù)據(jù)庫名稱] FROM 期待答案ING mysqldump databasename >路徑 及名字 恢復(fù)使用< Runtime runtime = Runtime.getRuntime(); runtime.exec("mysqldump table > d:/20070308.bak")

semovy 2007-05-11 17:30 發(fā)表評論
]]>
如何才能實現(xiàn)MySQL的自動備份http://m.tkk7.com/WshmAndLily/articles/116792.htmlsemovysemovyFri, 11 May 2007 08:54:00 GMThttp://m.tkk7.com/WshmAndLily/articles/116792.htmlhttp://m.tkk7.com/WshmAndLily/comments/116792.htmlhttp://m.tkk7.com/WshmAndLily/articles/116792.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/116792.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/116792.html
這個腳本每天最多只執(zhí)行一次,而且只保留最近五天的備份在服務(wù)器上。

代碼:

#!/bin/bash
#This is a ShellScript For Auto DB Backup
#Powered by ASPbiz
#2004-09

#Setting
#設(shè)置數(shù)據(jù)庫名,數(shù)據(jù)庫登錄名,密碼,備份路徑,日志路徑,數(shù)據(jù)文件位置,以及備份方式
#默認(rèn)情況下備份方式是tar,還可以是mysqldump,mysqldotcopy
#默認(rèn)情況下,用root(空)登錄mysql數(shù)據(jù)庫,備份至/root/dbxxxxx.tgz
DBName=mysql
DBUser=root
DBPasswd=
BackupPath=/root/
LogFile=/root/db.log
DBPath=/var/lib/mysql/
#BackupMethod=mysqldump
#BackupMethod=mysqlhotcopy
#BackupMethod=tar
#Setting End


NewFile="¥BackupPath"db¥(date +%y%m%d).tgz
DumpFile="¥BackupPath"db¥(date +%y%m%d)
OldFile="¥BackupPath"db¥(date +%y%m%d --date='5 days ago').tgz

echo "-------------------------------------------" >> ¥LogFile
echo ¥(date +"%y-%m-%d %H:%M:%S") >> ¥LogFile
echo "--------------------------" >> ¥LogFile
#Delete Old File
if [ -f ¥OldFile ]
then
rm -f ¥OldFile >> ¥LogFile 2>&1
echo "[¥OldFile]Delete Old File Success!" >> ¥LogFile
else
echo "[¥OldFile]No Old Backup File!" >> ¥LogFile
fi

if [ -f ¥NewFile ]
then
echo "[¥NewFile]The Backup File is exists,Can't Backup!" >> ¥LogFile
else
case ¥BackupMethod in
mysqldump)
if [ -z ¥DBPasswd ]
then
mysqldump -u ¥DBUser --opt ¥DBName > ¥DumpFile
else
mysqldump -u ¥DBUser -p¥DBPasswd --opt ¥DBName > ¥DumpFile
fi
tar czvf ¥NewFile ¥DumpFile >> ¥LogFile 2>&1
echo "[¥NewFile]Backup Success!" >> ¥LogFile
rm -rf ¥DumpFile
;;
mysqlhotcopy)
rm -rf ¥DumpFile
mkdir ¥DumpFile
if [ -z ¥DBPasswd ]
then
mysqlhotcopy -u ¥DBUser ¥DBName ¥DumpFile >> ¥LogFile 2>&1
else
mysqlhotcopy -u ¥DBUser -p ¥DBPasswd ¥DBName ¥DumpFile >>¥LogFile 2>&1
fi
tar czvf ¥NewFile ¥DumpFile >> ¥LogFile 2>&1
echo "[¥NewFile]Backup Success!" >> ¥LogFile
rm -rf ¥DumpFile
;;
*)
/etc/init.d/mysqld stop >/dev/null 2>&1
tar czvf ¥NewFile ¥DBPath¥DBName >> ¥LogFile 2>&1
/etc/init.d/mysqld start >/dev/null 2>&1
echo "[¥NewFile]Backup Success!" >> ¥LogFile
;;
esac
fi

echo "-------------------------------------------" >> ¥LogFile


semovy 2007-05-11 16:54 發(fā)表評論
]]>
Mysql日常自動備份和增量備份腳本http://m.tkk7.com/WshmAndLily/articles/116791.htmlsemovysemovyFri, 11 May 2007 08:51:00 GMThttp://m.tkk7.com/WshmAndLily/articles/116791.htmlhttp://m.tkk7.com/WshmAndLily/comments/116791.htmlhttp://m.tkk7.com/WshmAndLily/articles/116791.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/116791.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/116791.htmlMysql日常自動備份和增量備份腳本


你是否在尋找一個MySQL備份腳本?

適合對象

本文是在Linux下,mysql 4.1.14版本下測試的,經(jīng)過適當(dāng)修改可能適合mysql 4.0,5.0及其其他版本.

本文適合于沒有啟動復(fù)制功能的mysql,如果啟動了復(fù)制,可能不需要采取這種備份策略或者需要修改相關(guān)參數(shù).

每個人的備份策略都可能不同,所以請根據(jù)實際情況修改,做到舉一反三,不要照搬照抄,可能會造成不必要的損失.

希望你明白這個腳本要干什么工作!

腳本描述

每7天備份一次所有數(shù)據(jù),每天備份binlog,也就是增量備份.

(如果數(shù)據(jù)少,每天備份一次完整數(shù)據(jù)即可,可能沒必要做增量備份)

作者對shell腳本不太熟悉,所以很多地方寫的很笨 :)

開啟 bin log

在mysql 4.1版本中,默認(rèn)只有錯誤日志,沒有其他日志.可以通過修改配置打開bin log.方法很多,其中一個是在/etc/my.cnf中的mysqld部分加入:


[mysqld]
log-bin


這個日志的主要作用是增量備份或者復(fù)制(可能還有其他用途).

如果想增量備份,必須打開這個日志.

對于數(shù)據(jù)庫操作頻繁的mysql,這個日志會變得很大,而且可能會有多個.

在數(shù)據(jù)庫中flush-logs,或者使用mysqladmin,mysqldump調(diào)用flush-logs后并且使用參數(shù)delete-master-logs,這些日志文件會消失,并產(chǎn)生新的日志文件(開始是空的).

所以如果從來不備份,開啟日志可能沒有必要.

完整備份的同時可以調(diào)用flush-logs,增量備份之前flush-logs,以便備份最新的數(shù)據(jù).

完整備份腳本

如果數(shù)據(jù)庫數(shù)據(jù)比較多,我們一般是幾天或者一周備份一次數(shù)據(jù),以免影響應(yīng)用運行,如果數(shù)據(jù)量比較小,那么一天備份一次也無所謂了.

下載假設(shè)我們的數(shù)據(jù)量比較大,備份腳本如下:(參考過網(wǎng)絡(luò)上一個mysql備份腳本,致謝 :))


#!/bin/sh
# mysql data backup script
# by scud
http://www.jscud.com
# 2005-10-30
#
# use mysqldump --help,get more detail.
#
BakDir=/backup/mysql
LogFile=/backup/mysql/mysqlbak.log
DATE=`date +%Y%m%d`
echo " " >> $LogFile
echo " " >> $LogFile
echo "-------------------------------------------" >> $LogFile
echo $(date +"%y-%m-%d %H:%M:%S") >> $LogFile
echo "--------------------------" >> $LogFile
cd $BakDir
DumpFile=$DATE.sql
GZDumpFile=$DATE.sql.tgz
mysqldump --quick --all-databases --flush-logs
--delete-master-logs --lock-all-tables > $DumpFile
echo "Dump Done" >> $LogFile
tar czvf $GZDumpFile $DumpFile >> $LogFile 2>&1
echo "[$GZDumpFile]Backup Success!" >> $LogFile
rm -f $DumpFile
#delete previous daily backup files:采用增量備份的文件,如果完整備份后,則刪除增量備份的文件.
cd $BakDir/daily
rm -f *      
cd $BakDir  
echo "Backup Done!"
echo "please Check $BakDir Directory!"
echo "copy it to your local disk or ftp to somewhere !!!"
ls -al $BakDir


上面的腳本把mysql備份到本地的/backup/mysql目錄,增量備份的文件放在/backup/mysql/daily目錄下.

注意:上面的腳本并沒有把備份后的文件傳送到其他遠(yuǎn)程計算機(jī),也沒有刪除幾天前的備份文件:需要用戶增加相關(guān)腳本,或者手動操作.

增量備份

增量備份的數(shù)據(jù)量比較小,但是要在完整備份的基礎(chǔ)上操作,用戶可以在時間和成本上權(quán)衡,選擇最有利于自己的方式.

增量備份使用bin log,腳本如下:


#!/bin/sh
#
# mysql binlog backup script
#
/usr/bin/mysqladmin flush-logs
DATADIR=/var/lib/mysql
BAKDIR=/backup/mysql/daily
###如果你做了特殊設(shè)置,請修改此處或者修改應(yīng)用此變量的行:缺省取機(jī)器名,mysql缺省也是取機(jī)器名
HOSTNAME=`uname -n`
cd $DATADIR
FILELIST=`cat $HOSTNAME-bin.index`
##計算行數(shù),也就是文件數(shù)
COUNTER=0
for file in $FILELIST
do
COUNTER=`expr $COUNTER + 1 `
done
NextNum=0
for file in $FILELIST
do
        base=`basename $file`
NextNum=`expr $NextNum + 1`
if [ $NextNum -eq $COUNTER ]
then
echo "skip lastest"
          else
dest=$BAKDIR/$base
if(test -e $dest)
then
echo "skip exist $base"
else
echo "copying $base"
cp $base $BAKDIR
fi
fi
done
echo "backup mysql binlog ok"


增量備份腳本是備份前flush-logs,mysql會自動把內(nèi)存中的日志放到文件里,然后生成一個新的日志文件,所以我們只需要備份前面的幾個即可,也就是不備份最后一個.

因為從上次備份到本次備份也可能會有多個日志文件生成,所以要檢測文件,如果已經(jīng)備份過,就不用備份了.

注:同樣,用戶也需要自己遠(yuǎn)程傳送,不過不需要刪除了,完整備份后程序會自動生成.

訪問設(shè)置

腳本寫完了,為了能讓腳本運行,還需要設(shè)置對應(yīng)的用戶名和密碼,mysqladmin和mysqldump都是需要用戶名和密碼的,當(dāng)然可以寫在腳本中,但是修改起來不太方便,假設(shè)我們用系統(tǒng)的root用戶來運行此腳本,那么我們需要在/root(也就是root用戶的home目錄)創(chuàng)建一個.my.cnf文件,內(nèi)容如下


[mysqladmin]
password =password
user= root
[mysqldump]
user=root
password=password


注: 設(shè)置本文件只有root可讀.(chmod 600 .my.cnf )

此文件說明程序使用mysql的root用戶備份數(shù)據(jù),密碼是對應(yīng)的設(shè)置.這樣就不需要在腳本里寫用戶名和密碼了.

自動運行

為了讓備份程序自動運行,我們需要把它加入crontab.

有2種方法,一種是把腳本根據(jù)自己的選擇放入到/etc/cron.daily,/etc/cron.weekly這么目錄里.

一種是使用crontab -e放入到root用戶的計劃任務(wù)里,例如完整備份每周日凌晨3點運行,日常備份每周一-周六凌晨3點運行.

具體使用,請參考crontab的幫助.

所為何

在網(wǎng)上沒有找到類似的腳本,只好學(xué)習(xí)shell語法,自己寫了一個 :)

適合自己的,就是最好的!



semovy 2007-05-11 16:51 發(fā)表評論
]]>
用mysqldump 來備份數(shù)據(jù)庫http://m.tkk7.com/WshmAndLily/articles/96294.htmlsemovysemovySat, 27 Jan 2007 09:58:00 GMThttp://m.tkk7.com/WshmAndLily/articles/96294.htmlhttp://m.tkk7.com/WshmAndLily/comments/96294.htmlhttp://m.tkk7.com/WshmAndLily/articles/96294.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/96294.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/96294.html
用mysqldump 來備份數(shù)據(jù)庫

寫在前面:
-----------------------------------------------------------------
有時候經(jīng)常要把數(shù)據(jù)庫轉(zhuǎn)來轉(zhuǎn)去,或者導(dǎo)入導(dǎo)出,以前記得命令,后來又忘記了,現(xiàn)在寫出來備忘!
------------------------------------------------------------------

注意:mysqldump比直接拷貝數(shù)據(jù)庫文件夾速度要慢
但,直接復(fù)制文件夾不能100%轉(zhuǎn)移到其它機(jī)子上用,我說的不是windows下 :)

#mysqldump db_name >/path/name.sql

上面的命令意思是把一個庫導(dǎo)出到一個SQL文件. 當(dāng)然,你直接在有ROOT密碼的機(jī)子上執(zhí)行以上命令一定會報錯.所以,請用

#mysqldump db_name >/path/name.sql -uroot -p

這回會要求你輸入密碼,輸入正確,找找/path下是不是有name.sql文件了?

數(shù)據(jù)庫太大了,想壓縮一下?好,用這個命令就行

#mysqldump db_name |gzip >/path/name.gz -uroot -p

想備份全部的庫呢?

#mysqldump --all-databases? >/path/name.sql -uroot -p

#mysqldump --all-databases |gzip >/path/name.gz -uroot -p (很明顯,這條命令是加壓縮的意思)

只想備份一個單獨或者幾個表?

有時候數(shù)據(jù)庫很大很大,整個庫備份就不好管理,那就單獨備份

#mysqldump?db_name tab_name?>/path/sqlname.sql -uroot -p

備份做好了.遇到問題的時候.怎么用備份恢復(fù)數(shù)據(jù)?

再簡單不過了,

mysql?db_name?<?backup-file.sql -uroot -p

注意:如果你想恢復(fù)的數(shù)據(jù)庫是包含授權(quán)表的mysql數(shù)據(jù)庫,你需要用--skip-grant-table選項運行服務(wù)器。否則,它會抱怨不能找到授權(quán)表。在你已經(jīng)恢復(fù)表后,執(zhí)行mysqladmin flush-privileges告訴服務(wù)器裝載授權(quán)標(biāo)并使用它們?

恢復(fù)單個表

 恢復(fù)單個表較為復(fù)雜,如果你用一個由mysqldump生成的備份文件,并且它不包含你感興趣的表的數(shù)據(jù),你需要從相關(guān)行中提取它們并將它們用作mysql的輸入。這是容易的部分。難的部分是從只運用于該表的更新日志中拉出片斷。你會發(fā)覺mysql_find_rows實用程序?qū)Υ撕苡袔椭鼜母氯罩局刑崛《嘈胁樵儭?/font>

好了,就這些,看起來并不難,



semovy 2007-01-27 17:58 發(fā)表評論
]]>
mysql的級聯(lián)更新和級聯(lián)刪除http://m.tkk7.com/WshmAndLily/articles/89087.htmlsemovysemovyWed, 20 Dec 2006 09:47:00 GMThttp://m.tkk7.com/WshmAndLily/articles/89087.htmlhttp://m.tkk7.com/WshmAndLily/comments/89087.htmlhttp://m.tkk7.com/WshmAndLily/articles/89087.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/89087.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/89087.htmlcreate table user
(
userid integer not null auto_increment primary key,
username varchar(12) not null
)
type=innodb;

password表:
create table password
(
userid integer not null,
password varchar(12) not null,
index (userid),
foreign key (userid) references user (userid)
on delete cascade
on update cascade
)
type=innodb;

1、MySQL支持外鍵約束,并提供與其它DB相同的功能,但表類型必須為 InnoDB
2、建外鍵的表的那個列要加上index.


semovy 2006-12-20 17:47 發(fā)表評論
]]>
struts+MySQL實現(xiàn)圖片的存儲與顯示http://m.tkk7.com/WshmAndLily/articles/88347.htmlsemovysemovySun, 17 Dec 2006 08:30:00 GMThttp://m.tkk7.com/WshmAndLily/articles/88347.htmlhttp://m.tkk7.com/WshmAndLily/comments/88347.htmlhttp://m.tkk7.com/WshmAndLily/articles/88347.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/88347.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/88347.html 人事信息管理系統(tǒng)中,需要管理用戶的個人身份照片。通常這種格式的照片只有幾 K 到幾十 K 大小,保存在數(shù)據(jù)庫中易于進(jìn)行管理和維護(hù)(如果放在文件夾下容易發(fā)生誤操作而引起數(shù)據(jù)被修改或丟失)。

功能設(shè)計: 給用戶提供一個上傳的界面,并設(shè)定上傳文件的尺寸上限。用戶上傳的照片先統(tǒng)一保存在一個臨時文件夾中,之后可以用 <img> 指向臨時文件夾中的這個圖片,讓用戶可以預(yù)覽自己上傳的照片。當(dāng)所有的用戶信息都收集完成后,將圖片和其他信息一并提交,保存到數(shù)據(jù)庫中。保存成功以后,刪除臨時文件夾中的圖片。

實現(xiàn)步驟:

我使用的是從 struts 主頁上下載的 struts-1.2.8-src ,其中 web/examples/ 目錄下有一個 upload 的例子,稍微修改了一下就直接拿過來用了。這是一個 JSP 頁面、 ActionForm Action 的組合。下面分別列出各自的代碼。

upload.jsp 的部分源代碼:

<html:form action="/UploadSubmit" enctype="multipart/form-data">?????

????? 請選擇需要上傳的照片 :

???? <html:file property="theFile"/>

???? <html:submit value=" 上傳 "/>?????

</html:form>

接下來需要在 ActionForm 中聲明這個屬性,并設(shè)置 getter setter 方法,這部分源代碼如下:

public class UploadForm extends ActionForm {

??? protected FormFile theFile;

??? public FormFile getTheFile() {

??????? return theFile;

??? }

??? public void setTheFile(FormFile theFile) {

??????? this.theFile = theFile;

??? }

}

這個表單的 theFile 屬性不是 String boolean ,而是 org.apache.struts.upload.FormFile 。因為用戶上傳的是一個二進(jìn)制文件,而 HTTP 協(xié)議是以文本形式傳輸數(shù)據(jù)的,這就需要進(jìn)行轉(zhuǎn)換。打個比方,一輛汽車需要從甲地送到乙地,但是兩地之間只有一條索道,汽車沒法開,所以就想個辦法在甲地把汽車先拆了,把零件送到乙地再重新組裝成一輛汽車。 FormFile 起的就是拆卸和組裝的作用,只不過它把拆卸、傳輸和組裝的過程都封裝起來了,我們看到的是一輛汽車從甲地開進(jìn) FormFile ,過一會它就從乙地開出來了 J 我們要決定的只是把它停到什么地方,這就是 Action 的活了。

按照功能設(shè)計, Action 要把這部車停到一個臨時文件夾下面,這部分源代碼如下:

public ActionForward execute(ActionMapping mapping,

???????????????????????????????? ActionForm form,

???????????????????????????????? HttpServletRequest request,

???????????????????????????????? HttpServletResponse response)

??????? throws Exception {

??????? if (form instanceof UploadForm) {

??????????? UploadForm theForm = (UploadForm) form;

????? ?????? // 獲取上傳的數(shù)據(jù)文件

??????????? FormFile file = theForm.getTheFile();

??????????? // 獲取文件名

??????????? String filename= file.getFileName();

??????????? // 設(shè)置圖片文件臨時存放的路徑

??????????? HttpSession session = request.getSession();

??????????? String path = session.getServletContext().getRealPath("/") + "temp\\" + filename;

??????????? try {

??????????????? // 讀取文件中的數(shù)據(jù),獲取二進(jìn)制的數(shù)據(jù)流

???????????? InputStream stream = file.getInputStream();

???????????? // 把數(shù)據(jù)寫到指定路徑

???????????? OutputStream bos = new FileOutputStream(path);

???????????? int bytesRead = 0;

???????????? byte[] buffer = new byte[8192];

???????????? while ((bytesRead = stream.read(buffer, 0, 8192)) != -1) {

???????????????? bos.write(buffer, 0, bytesRead);

???????????? }

???????????? bos.close();

???????????? logger.info("The file has been written to \""

???????????????????? ? + path + "\"");

??????????????? // 設(shè)計一個標(biāo)記,說明用戶已經(jīng)上傳過照片了。 ??????????????

???????????? session.setAttribute("imageuploaded","true");

???????????? session.setAttribute("filename",filename);

???????????? // close the stream

???????????? stream.close();

???????????? bos.flush();

???????????? bos.close();

??????????? }catch (FileNotFoundException fnfe) {

??????????????? return null;

??????????? }catch (IOException ioe) {

??????????????? return null;

??????????? }

??????????? //destroy the temporary file created

??????????? file.destroy();

??????????? // 轉(zhuǎn)向下一個頁面

??????????? return mapping.findForward("next");

??????? }

????? ??//this shouldn't happen in this example

??????? return null;

??? }

這樣圖片就被放在 temp 的臨時文件夾下,顯示的時候,只需要先檢查一下標(biāo)記,看看用戶是否上傳了照片,如果已經(jīng)上傳,就用一個 <img src=””> 引用這個圖片。還有一個小地方需要修改,因為限定上傳的是身份照片,需要限定一個尺寸上限,這個在 struts upload 里面有現(xiàn)成的例子。先在 struts-config.xml 中配置這個 ActionForm Action

<form-bean name="uploadForm"

?type="org.apache.struts.webapp.upload.UploadForm"/>

……

<action input="/pages/hr/error.jsp" name="uploadForm"

? ??????? path="/UploadSubmit" scope="request"

type="org.apache.struts.webapp.upload.UploadAction" validate="true">

?? <forward name="next" path="/pages/hr/input.jsp"/>

</action>

……

<controller maxFileSize="2M" inputForward="true" />

在配置文件中已經(jīng)看到 <action> validate 屬性被設(shè)置成“ true ”,這就是說表單提交之前先要對其內(nèi)容進(jìn)行驗證,這里我們要驗證的就是 theFile 是否超出了 controller 中設(shè)定的最大尺寸 2M 。這個驗證是通過 ActionForm validate 方法來實現(xiàn)的:

/**

???? * Check to make sure the client hasn't exceeded the maximum allowed upload size inside of this validate method.

**/

??? public ActionErrors validate(ActionMapping mapping,

??????? HttpServletRequest request) {???????????

??????? ActionErrors errors = null;

??????? //has the maximum length been exceeded?

??????? Boolean maxLengthExceeded =

??????????? (Boolean) request.getAttribute(

??????????????? MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED);???????????????

??????? if ((maxLengthExceeded != null) && (maxLengthExceeded.booleanValue())) {

??????????? errors = new ActionErrors();

??????????? errors.add(

??????????????? ActionMessages.GLOBAL_MESSAGE ,

??????????????? new ActionMessage("maxLengthExceeded"));

??????????? errors.add(

??????????????? ActionMessages.GLOBAL_MESSAGE ,

??????????????? new ActionMessage("maxLengthExplanation"));

??????? }

??????? return errors;

??? }

這里我估計有個 hook 之類的東西先截獲了表單(應(yīng)該和 controller 有關(guān)),對 theFile 的尺寸進(jìn)行校驗,然后把結(jié)果保存在 request scope 中。 Validate 方法只要檢查一下這個結(jié)果就可以了,如果尺寸超標(biāo),表單就不會被提交給 Action

以上算是完成了第一步,從用戶那里拿到照片,并保存在臨時文件夾當(dāng)中。接下來要做的就是把照片保存到 MySQL 數(shù)據(jù)庫中,這個字段我用的是 MEDIUMBLOB ,因為 BLOB 最大長度是 216-1 字節(jié),大約 64K MEDIUMBLOB 224-1 字節(jié),約 16M ,足夠用了。保存圖片的主要代碼如下:

/**

?* 將用戶的照片保存在數(shù)據(jù)表中,添加成功后,刪除臨時文件夾中的圖片。

?* @param id 用戶的身份號,作為圖片的標(biāo)識碼

?* @param path 圖片存放的路徑。一般存放在一個臨時文件夾中。

?* @return

?*/

public static void saveImage(int id, String path) throws SQLException{

???? String time = new java.util.Date().toString();

???? Connection conn = null;

???? PreparedStatement pstmt = null;

???? boolean flag = false;

???? // 獲取連接

???? try {

???????? conn = DbManager.getConnection();

???????? logger.info(time + ":saveImage() DbManager 數(shù)據(jù)庫連接池獲取一個連接。 ");

???? } catch (SQLException e) {

???????? // 如果沒有能夠從 DbManager 獲取連接,此次查詢操作失敗

???????? logger.error(time + ": saveImage() 不能獲取數(shù)據(jù)庫連接,無法保存圖片! ");

???????? throw new SQLException(":saveImage() 不能獲取數(shù)據(jù)庫連接,無法保存圖片! ");

???? }

????

???????? // 執(zhí)行查詢

???? try {

???????? pstmt = conn.prepareStatement("UPDATE hr01 SET hr01_photo=? where hr01_id=?");

???????? FileInputStream in = new FileInputStream(path);

???????? pstmt.setBinaryStream(1,in,in.available());

???????? pstmt.setInt(2,id);???? ???

???????? pstmt.executeUpdate();

???????? pstmt.executeUpdate("COMMIT");

???????? logger.info(" 圖片 " + path + " 被添加到數(shù)據(jù)庫中! ");

???????? flag = true;???????????

???? }catch(IOException e){

???????? logger.error(" 圖片 " + path + " 文件讀寫錯誤!請檢查文件路徑是否正確 ");

???????? throw new SQLException(" 無法保存圖片! ");

???? }catch (SQLException ex) {

???????? logger.error(new java.util.Date() + "Error:Insert into table."

???????????????? + ex.getMessage());????????

???????? logger.error(" 圖片 " + path +" 沒有被保存到數(shù)據(jù)庫 .");

???????? throw new SQLException(" 圖片 " + path +" 沒有被保存到數(shù)據(jù)庫 .");

????????

???? } finally {

???????? try {

???????????? pstmt.close();

???????????? conn.close();

???????????? logger.info("DbHrinfo saveImage() closed the connection created at " + time);

???????? } catch (SQLException e) {

???????? }

???? }
>????

???? // 圖片添加成功以后就刪除臨時文件夾中的圖片數(shù)據(jù)

???? if(flag == true){

???????? File file = new File(path);

???????? if(file.exists()){

???????????? file.delete();

???????? }

???? }

}

需要注意的是 pstmt.executeUpdate("COMMIT"); 這行代碼,最初我并沒有寫這行,程序能順利執(zhí)行,日志中也顯示“圖片××被添加到數(shù)據(jù)庫中”,但是到庫里一查詢,什么都沒有。 SQL 語句被提交,但是數(shù)據(jù)庫里面沒有即時的顯示,估計是緩沖區(qū)的作用,它把我的 SQL 語句緩存起來而不是立即提交給數(shù)據(jù)庫。后來我在 textpad 里面單獨執(zhí)行這段代碼,發(fā)現(xiàn)不用“ COMMIT SQL 語句就立即被提交了。這個地方還沒有弄清楚,以后需要繼續(xù)研究。

功能上做一點小改進(jìn),用戶提交了照片以后,瀏覽了一下覺得不滿意,只要還沒有最終提交數(shù)據(jù),當(dāng)然允許他重新上傳一個照片。我們只需要在 <img src=””> 下面提供一個“重新提交”的鏈接就可以了。這個鏈接指向一個 AlterImageAction ,它的功能就是清除 session 中用戶已經(jīng)上傳照片的標(biāo)記,并把剛才保存到臨時文件夾中的照片刪掉,等待用戶重新上傳。這部分代碼如下:

public ActionForward execute(ActionMapping mapping,

???????? ActionForm form,HttpServletRequest request,

???????? HttpServletResponse response)

throws IOException,ServletException{

????????

???? HttpSession session = request.getSession();

??????? //1. 從臨時文件夾中刪除圖片

???? String filename = (String)session.getAttribute("filename");

???? String path = session.getServletContext().getRealPath("/")

+ "temp\\" + filename;

???? File file = new File(path);

???? if(file.exists()){

???????? file.delete();

???????? logger.info(" 文件 " + path + " 已經(jīng)被刪除 ");

???? }

????

???? //2. session 中清除上傳圖片的標(biāo)記

????

???? session.removeAttribute("imageuploaded");

???? session.removeAttribute("filename");???????

???? return mapping.findForward("next");????

}

提交和保存到此功德圓滿。下次用戶想要查詢自己的信息的時候,因為臨時文件夾中已經(jīng)沒有用戶照片,需要從數(shù)據(jù)庫中讀取。用一個 ShowImageAction 來實現(xiàn)這個功能:

public ActionForward execute(ActionMapping mapping,

???????? ActionForm form, HttpServletRequest request,

???????? HttpServletResponse response)

throws IOException,ServletException{

???? // 需要的情況下設(shè)置數(shù)據(jù)源

???? if (!DbManager.hasSetDataSource()) {

???????? javax.sql.DataSource dataSource;

???????? try {

???????????? dataSource = getDataSource(request);

???????????? DbManager.setDataSource(dataSource);

???????? } catch (Exception e) {

???????????? logger.error(e.getMessage());

???????????? mapping.findForward("error");

???????? }

???? }

????

???? String photo_no = request.getParameter("photo_no");

???? Connection conn = null;

???? Statement stmt = null;

???? // 獲取連接

???? try {

???????? conn = DbManager.getConnection();

???????? logger.info("showimage.jsp DbManager 數(shù)據(jù)庫連接池獲取一個連接。 ");

???? } catch (SQLException e) {

???????? // 如果沒有能夠從 DbManager 獲取連接,此次查詢操作失敗

??????? logger.error(" showimage.jsp 不能獲取數(shù)據(jù)庫連接,無法讀取圖片! ");

???? }

???? try {

???????? // 準(zhǔn)備語句執(zhí)行對象

???????? stmt = conn.createStatement();

???????? String sql = " SELECT hr01_photo FROM hr01 WHERE hr01_id='" + photo_no + "'";

???????? ResultSet rs = stmt.executeQuery(sql);

???????? if (rs.next()) {

???????????? InputStream in = rs.getBinaryStream("hr01_photo");

???????????? int bytesRead = 0;

byte[] buffer = new byte[8192];

???????????? response.setContentType("image/jpeg");

???????????? response.setContentLength(in.available());

???????????? OutputStream outs = response.getOutputStream();

???? ???????????????????????

???????????? while ((bytesRead = in.read(buffer, 0, 8192)) != -1) {

???????????????? outs.write(buffer, 0, bytesRead);

???????????? }

???????????? outs.flush();

???????????? in.close();

???????????? rs.close();

???????? } else {

???????????? rs.close();

???????????? response.sendRedirect("error.jsp");

???????? }

???? }catch(SQLException e){

????????

???? }finally {

???????? try{

???????? stmt.close();

???????? conn.close();

???????? }catch(SQLException ex){

????????????

???????? }

???? }

???? return null;

}

以前一直不清楚 execute 方法中的 response 參數(shù)的用法,因為處理完以后總要 redirect 到另外一個頁面,所以用的最多的就是把數(shù)據(jù)保存在 session 中,在另一個頁面里再取出來用。這次純粹是試驗性地在 response 中寫入 image/jpeg 內(nèi)容,然后返回一個 null 值。最后的執(zhí)行結(jié)果跟我預(yù)期的一樣,在瀏覽器中直接顯示從數(shù)據(jù)庫中讀出的圖片。那么接下來就很好做了,只需要在 JSP 頁面中設(shè)置一個 <image> 標(biāo)簽,指向這個 Action 就可以,當(dāng)然,在這之前需要在 struts-config.xml 中先部署這個 Action

<action path="/ShowImage"

?type="software.action.ShowImageAction"></action>

然后在 JSP 頁面中引用這個 Action 來顯示圖像 :

<img src="/tibet/ShowImage.do?photo_no=666542">


< p>

semovy 2006-12-17 16:30 發(fā)表評論
]]>
Mysql與JSP網(wǎng)頁中文亂碼問題的解決方案(轉(zhuǎn)載)http://m.tkk7.com/WshmAndLily/articles/86640.htmlsemovysemovySun, 10 Dec 2006 02:10:00 GMThttp://m.tkk7.com/WshmAndLily/articles/86640.htmlhttp://m.tkk7.com/WshmAndLily/comments/86640.htmlhttp://m.tkk7.com/WshmAndLily/articles/86640.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/86640.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/86640.html自從以前學(xué)習(xí)JSP開始,中文亂碼問題就一直不斷,苦不堪言。這次在項目開始之前,我們要解決的第一個問題就是把mysql的中文亂碼問題搞定。經(jīng)過多天的努力,終于成功的解決了中文亂碼問題,特寫在這里,以備后用。

軟件及環(huán)境:Windows XP(2000), j2sdk1.4.2, Tomcat 5.0.25, mysql 4.1, EMS Mysql Manager 2(方便建表,版本2.8.5.1),驅(qū)動為mysql-connector-java-3.1.4-beta-bin.jar。

目標(biāo):在該環(huán)境下,實現(xiàn)中文的正常顯示,讀取與插入數(shù)據(jù)庫。

注:我只在此環(huán)境下測試通過,別的系統(tǒng)及不同版本未測試

要點:統(tǒng)一字符集(JSP頁面編碼,mysql建庫時字符集選擇,連接數(shù)據(jù)庫URL,request設(shè)定等)
-------我自己的
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES 'gbk' */;

#drop database named teckoparts

drop database if exists teckoparts;

#create database named teckoparts

create database teckoparts;

#use database teckoparts

use teckoparts;

#create table catalog
create table catalog
(
?id varchar(255) not null primary key,
?parentId varchar(128) not null,
?text_en? varchar(256) not null,
?text_hk? varchar(256) ,
?text_ch? varchar(256),
?info???? varchar(1024)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

insert into catalog values('1','0','teckoparts','達(dá)藝零件','達(dá)藝零件','總目錄');

#create?table admin
create table admin
(
?id int(11) not null primary key,
?userName? varchar(128) not null,
?passWord? varchar(12)? not null,
?role?? char(1)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

insert into admin values(1,'admin','admin','1');

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

下面我以GBK為例講解。如果要使用utf-8,只要在相應(yīng)的GBK處換成utf-8即可

--------------------------- 步驟1 以GBK字符集建庫建表 -------------------------------------

我使用EMS來建mysql的數(shù)據(jù)庫及表,因為它是圖形界面,方便操作(就像SQL SERVER 2000中的企業(yè)管理器一樣)。

建庫時,從EMS菜單中選create Database...新建一個數(shù)據(jù)庫,CharacterSet選gbk_bin(另一個gbk_chinese_ci不知道與這個有什么區(qū)別,我找資料也沒有找到。如果你知道,請告訴我,我補充在這里)。不要把工具欄上有一個加號和數(shù)據(jù)庫模樣的圖標(biāo)當(dāng)成新建數(shù)據(jù)庫了,那個新注冊一個已經(jīng)存在的數(shù)據(jù)庫。
后面建表時,也要選擇同樣的字符集。

建好后,此時不要用EMS向里面插入數(shù)據(jù),否則你看到的中文依然是亂碼。

--------------------------- 步驟2 連接數(shù)據(jù)庫的URL后加些參數(shù) -------------------------------

假設(shè)我新建的數(shù)據(jù)庫是testdb,那么我連接數(shù)據(jù)庫的url應(yīng)該為:

jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=gbk

此時要注意:如果我是把這個url寫在JAVA代碼中,就直接這樣寫。但如果是在xml配置文件中(如struts-config.xml,web.xml等),要把其中的&改為&amp;才行,否則會出錯。也就是:

jdbc:mysql://localhost:3306/testdb?useUnicode=true&amp;characterEncoding=gbk

--------------------------- 步驟3 每個JSP頁面都要聲明該中文字符集 ----------------------------

在每個JSP頁面的最上面都加上一句

<%@ page language="java" contentType="text/html;charset=GBK" %>

這樣才能保證JSP頁面中的中文顯示正常

--------------------------- 步驟4 加一個傳遞參數(shù)時設(shè)定request字符集的filter類 -----------------------

因為網(wǎng)絡(luò)中字符在傳遞的時候,都是統(tǒng)一以iso-8859-1的編碼傳遞,所以我們必須對request重新設(shè)定字符集,才能正常顯示中文。如果采用filter類來實現(xiàn),我們不用在每次取中文參數(shù)時都要重新設(shè)定。

filter類的內(nèi)容:

/*
* ====================================================================
*
* JavaWebStudio 開源項目
*
* Struts_db v0.1
*
* ====================================================================
*/
package com.strutsLogin.util;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
* 中文過濾器
*/
public class SetCharacterEncodingFilter implements Filter {

// ----------------------------------------------------- Instance Variables

/**
* The default character encoding to set for requests that pass through
* this filter.
*/
protected String encoding = null;

/**
* The filter configuration object we are associated with. If this value
* is null, this filter instance is not currently configured.
*/
protected FilterConfig filterConfig = null;

/**
* Should a character encoding specified by the client be ignored?
*/
protected boolean ignore = true;

// --------------------------------------------------------- Public Methods

/**
* Take this filter out of service.
*/
public void destroy() {

this.encoding = null;
this.filterConfig = null;

}

/**
* Select and set (if specified) the character encoding to be used to
* interpret request parameters for this request.
*
* @param request The servlet request we are processing
* @param result The servlet response we are creating
* @param chain The filter chain we are processing
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {

// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null)) {
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}

// Pass control on to the next filter
chain.doFilter(request, response);

}

/**
* Place this filter into service.
*
* @param filterConfig The filter configuration object
*/
public void init(FilterConfig filterConfig) throws ServletException {

this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;

}

// ------------------------------------------------------ Protected Methods

/**
* Select an appropriate character encoding to be used, based on the
* characteristics of the current request and/or filter initialization
* parameters. If no character encoding should be set, return
* <code>null</code>.
* <p>
* The default implementation unconditionally returns the value configured
* by the <strong>encoding</strong> initialization parameter for this
* filter.
*
* @param request The servlet request we are processing
*/
protected String selectEncoding(ServletRequest request) {

return (this.encoding);

}

}//EOC


該代碼來自于www.javawebstudio.com,特此感謝!

然后我們在web.xml中加一些配置,就可以了,配置如下:

<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>javawebstudio.struts_db.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<servlet-name>action</servlet-name>
</filter-mapping>

放在web.xml的合適位置。一般在最后,<jsp-config>標(biāo)簽之前(如果有的話)

經(jīng)過以上步驟,JSP和mysql的中文顯示及插入就都正常了。在STRUTS中也正常。

但是,此時如果你用EMS或mysql的命令行控制臺來看表中的數(shù)據(jù),卻發(fā)現(xiàn)它們都是????。這是怎么回事呢?

不用擔(dān)心,只要我們運行下面的這幾行命令,就能看到正常的中文了!

SET character_set_client = gbk;
SET character_set_connection = gbk;
SET character_set_database = gbk;
SET character_set_results = gbk;
SET character_set_server = gbk;

SET collation_connection = gbk_bin;
SET collation_database = gbk_bin;
SET collation_server = gbk_bin;

如果你用的是mysql的命令行,則直接輸入就好。

如果是EMS,則在工具欄中有一個Show SQL Editor按鈕,點一下,把上面的命令輸入,再按一個"execute"的按鈕,就行了!

而且在這種情況下,你可以甚至可以用中文名來建數(shù)據(jù)庫,表名和字段名!!!!

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

但是有一點要特別注意!

像GBK,UTF-8這樣的名字,在mysql與JAVA中有不同的規(guī)定,寫的時候要格外注意,否則會出錯。

比如GBK,在JAVA中要寫成GBK,但在mysql中要寫成gbk(連接數(shù)據(jù)庫的URL)

比如UTF-8,在JAVA中要寫成UTF-8,但在Mysql中要寫成utf8

其它的字集符也有類似的區(qū)別



semovy 2006-12-10 10:10 發(fā)表評論
]]>
MySQL Join詳解http://m.tkk7.com/WshmAndLily/articles/76554.htmlsemovysemovySat, 21 Oct 2006 09:30:00 GMThttp://m.tkk7.com/WshmAndLily/articles/76554.htmlhttp://m.tkk7.com/WshmAndLily/comments/76554.htmlhttp://m.tkk7.com/WshmAndLily/articles/76554.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/76554.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/76554.htmlcreate table emp(
id int not null primary key,
name varchar(10)
);

create table emp_dept(
dept_id varchar(4) not null,
emp_id int not null,
emp_name varchar(10),
primary key (dept_id,emp_id));

insert into emp() values
(1,"Dennis-1"),
(2,"Dennis-2"),
(3,"Dennis-3"),
(4,"Dennis-4"),
(5,"Dennis-5"),
(6,"Dennis-6"),
(7,"Dennis-7"),
(8,"Dennis-8"),
(9,"Dennis-9"),
(10,"Dennis-10");

insert into emp_dept() values
("R&D",1,"Dennis-1"),
("DEv",2,"Dennis-2"),
("R&D",3,"Dennis-3"),
("Test",4,"Dennis-4"),
("Test",5,"Dennis-5");

>> left join
-------------
select a.id,a.name,b.dept_id
from emp a left join emp_dept b on (a.id=b.emp_id);

# 挑出左邊的 table emp 中的所有資料,即使 emp_dept 中沒有的資料也挑出來,沒有的就用 NULL 來顯示,
# 也即顯示資料是以左邊的 table emp 中的資料為基礎(chǔ)

mysql> select a.id,a.name,b.dept_id
-> from emp a left join emp_dept b on (a.id=b.emp_id);
+----+-----------+---------+
| id | name | dept_id |
+----+-----------+---------+
| 1 | Dennis-1 | R&D |
| 2 | Dennis-2 | DEv |
| 3 | Dennis-3 | R&D |
| 4 | Dennis-4 | Test |
| 5 | Dennis-5 | Test |
| 6 | Dennis-6 | NULL |
| 7 | Dennis-7 | NULL |
| 8 | Dennis-8 | NULL |
| 9 | Dennis-9 | NULL |
| 10 | Dennis-10 | NULL |
+----+-----------+---------+

# 挑出 table emp 中有而 table emp_dept 中沒有的人員資料
select a.id,a.name,b.dept_id
from emp a left join emp_dept b on (a.id=b.emp_id)
where b.dept_id IS NULL;

mysql> select a.id,a.name,b.dept_id
-> from emp a left join emp_dept b on (a.id=b.emp_id)
-> where b.dept_id IS NULL;
+----+-----------+---------+
| id | name | dept_id |
+----+-----------+---------+
| 6 | Dennis-6 | NULL |
| 7 | Dennis-7 | NULL |
| 8 | Dennis-8 | NULL |
| 9 | Dennis-9 | NULL |
| 10 | Dennis-10 | NULL |
+----+-----------+---------+

# 把 table emp_dept 放在左邊的情形(當(dāng)然以 emp_dept 中的數(shù)據(jù)為基礎(chǔ)來顯示資料,emp 中比emp_dept 中多的資料也就不會顯示出來了):

select a.id,a.name,b.dept_id
from emp_dept b left join emp a on (a.id=b.emp_id);
mysql> select a.id,a.name,b.dept_id
-> from emp_dept b left join emp a on (a.id=b.emp_id);
+------+----------+---------+
| id | name | dept_id |
+------+----------+---------+
| 2 | Dennis-2 | DEv |
| 1 | Dennis-1 | R&D |
| 3 | Dennis-3 | R&D |
| 4 | Dennis-4 | Test |
| 5 | Dennis-5 | Test |
+------+----------+---------+

>> right join
---------------
select a.id,a.name,b.dept_id
from emp a right join emp_dept b on (a.id=b.emp_id);
# 挑資料時以右邊 table emp_dept 中的資料為基礎(chǔ)來顯示資料

mysql> select a.id,a.name,b.dept_id
-> from emp a right join emp_dept b on (a.id=b.emp_id);
+------+----------+---------+
| id | name | dept_id |
+------+----------+---------+
| 2 | Dennis-2 | DEv |
| 1 | Dennis-1 | R&D |
| 3 | Dennis-3 | R&D |
| 4 | Dennis-4 | Test |
| 5 | Dennis-5 | Test |
+------+----------+---------+
5 rows in set (0.00 sec)

# 我們再把 table 的位置交換一下,再用 right join 試試

select a.id,a.name,b.dept_id
from emp_dept b right join emp a on (a.id=b.emp_id);

mysql> select a.id,a.name,b.dept_id
-> from emp_dept b right join emp a on (a.id=b.emp_id);
+----+-----------+---------+
| id | name | dept_id |
+----+-----------+---------+
| 1 | Dennis-1 | R&D |
| 2 | Dennis-2 | DEv |
| 3 | Dennis-3 | R&D |
| 4 | Dennis-4 | Test |
| 5 | Dennis-5 | Test |
| 6 | Dennis-6 | NULL |
| 7 | Dennis-7 | NULL |
| 8 | Dennis-8 | NULL |
| 9 | Dennis-9 | NULL |
| 10 | Dennis-10 | NULL |
+----+-----------+---------+

# 是不是和 left join 一樣了?

>> direct join
--------------
# 如果用right join 同不用 Join 直接挑資料是相同的,它等介於以下的指令

select a.id,a.name,b.dept_id
from emp a ,emp_dept b
where a.id=b.emp_id;

mysql> select a.id,a.name,b.dept_id
-> from emp a ,emp_dept b
-> where a.id=b.emp_id;
+----+----------+---------+
| id | name | dept_id |
+----+----------+---------+
| 2 | Dennis-2 | DEv |
| 1 | Dennis-1 | R&D |
| 3 | Dennis-3 | R&D |
| 4 | Dennis-4 | Test |
| 5 | Dennis-5 | Test |
+----+----------+---------+

怎樣,弄明白了嗎?



semovy 2006-10-21 17:30 發(fā)表評論
]]>
MySQL語法語句大全http://m.tkk7.com/WshmAndLily/articles/76553.htmlsemovysemovySat, 21 Oct 2006 09:24:00 GMThttp://m.tkk7.com/WshmAndLily/articles/76553.htmlhttp://m.tkk7.com/WshmAndLily/comments/76553.htmlhttp://m.tkk7.com/WshmAndLily/articles/76553.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/76553.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/76553.html一、SQL速成?
結(jié)構(gòu)查詢語言(SQL)是用于查詢關(guān)系數(shù)據(jù)庫的標(biāo)準(zhǔn)語言,它包括若干關(guān)鍵字和一致的語法,便于數(shù)據(jù)庫元件(如表、索引、字段等)的建立和操縱。?
以下是一些重要的SQL快速參考,有關(guān)SQL的語法和在標(biāo)準(zhǔn)SQL上增加的特性,請查詢MySQL手冊。?
1.創(chuàng)建表?
表是數(shù)據(jù)庫的最基本元素之一,表與表之間可以相互獨立,也可以相互關(guān)聯(lián)。創(chuàng)建表的基本語法如下:?
create table table_name?
(column_name data無效 {identity |null|not null},?
…)?
其中參數(shù)table_name和column_name必須滿足用戶數(shù)據(jù)庫中的識別器(identifier)的要求,參數(shù)data無效是一個標(biāo)準(zhǔn)的SQL類型或由用戶數(shù)據(jù)庫提供的類型。用戶要使用non-null從句為各字段輸入數(shù)據(jù)。?
create table還有一些其他選項,如創(chuàng)建臨時表和使用select子句從其他的表中讀取某些字段組成新表等。還有,在創(chuàng)建表是可用PRIMARY KEY、KEY、INDEX等標(biāo)識符設(shè)定某些字段為主鍵或索引等。?
書寫上要注意:?
在一對圓括號里的列出完整的字段清單。?
字段名間用逗號隔開。?
字段名間的逗號后要加一個空格。?
最后一個字段名后不用逗號。?
所有的SQL陳述都以分號";"結(jié)束。?
例:?
mysql> CREATE TABLE test (blob_col BLOB, index(blob_col(10)));?

2.創(chuàng)建索引?
索引用于對數(shù)據(jù)庫的查詢。一般數(shù)據(jù)庫建有多種索引方案,每種方案都精于某一特定的查詢類。索引可以加速對數(shù)據(jù)庫的查詢過程。創(chuàng)建索引的基本語法如下:?
create index index_name?
on table_name (col_name[(length)],... )?
例:?
mysql> CREATE INDEX part_of_name ON customer (name(10));?

3.改變表結(jié)構(gòu)?
在數(shù)據(jù)庫的使用過程中,有時需要改變它的表結(jié)構(gòu),包括改變字段名,甚至改變不同數(shù)據(jù)庫字段間的關(guān)系。可以實現(xiàn)上述改變的命令是alter,其基本語法如下:?
alter table table_name alter_spec [, alter_spec ...]?
例:?
mysql> ALTER TABLE t1 CHANGE a b INTEGER;?

4.刪除數(shù)據(jù)對象?
很多數(shù)據(jù)庫是動態(tài)使用的,有時可能需要刪除某個表或索引。大多數(shù)數(shù)據(jù)庫對象可以下面的命令刪除:?
drop object_name?
mysql> DROP TABLE tb1;?

5.執(zhí)行查詢?
查詢是使用最多的SQL命令。查詢數(shù)據(jù)庫需要憑借結(jié)構(gòu)、索引和字段類型等因素。大多數(shù)數(shù)據(jù)庫含有一個優(yōu)化器(optimizer),把用戶的查詢語句轉(zhuǎn)換成可選的形式,以提高查詢效率。?
值得注意的是MySQL不支持SQL92標(biāo)準(zhǔn)的嵌套的where子句,即它只支持一個where子句。其基本語法如下:?
SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [HIGH_PRIORITY]?
[DISTINCT | DISTINCTROW | ALL]?
select_expression,...?
[INTO {OUTFILE | DUMPFILE} ’file_name’ export_options]?
[FROM table_references?
][WHERE where_definition]?
[GROUP BY col_name,...]?
[HAVING where_definition]?
[ORDER BY {unsigned_integer | col_name | formula} ][ASC | DESC] ,...]?
[LIMIT ][offset,] rows]?
[PROCEDURE procedure_name] ]?
其中where從句是定義選擇標(biāo)準(zhǔn)的地方,where_definition可以有不同的格式,但都遵循下面的形式:?
字段名操作表達(dá)式?
字段名操作字段名?
在第一種形式下,標(biāo)準(zhǔn)把字段的值與表達(dá)式進(jìn)行比較;在第二種形式下,把兩個字段的值進(jìn)行比較。根據(jù)所比較的數(shù)據(jù)類型,search_condition中的操作可能選以下幾種:?
= 檢查是否相等?
!= 檢查是否不等?

> (或>=) 檢查左邊值是否大于(或大于等于)右邊值?
< (或<=) 檢查左邊值是否小于(或小于等于)右邊值?
[not] between 檢查左邊值是否在某個范圍內(nèi)?
[not] in 檢查左邊是否某個特定集的成員?
[not] like 檢查左邊是否為右邊的子串?
is [not] null 檢查左邊是否為空值?
在這里,可以用通配符_代表任何一個字符,%代表任何字符串。使用關(guān)鍵字<AND>、<OR>和<NOT>可以生成復(fù)雜的詞,它們運行檢查時使用布爾表達(dá)式的多重標(biāo)準(zhǔn)集。?
例:?
mysql> select t1.name, t2.salary from employee AS t1, info AS t2 where t1.name = t2.name;?
mysql> select college, region, seed from tournament?
ORDER BY region, seed;?
mysql> select col_name from tbl_name WHERE col_name > 0;?

6.修改表中數(shù)據(jù)?
在使用數(shù)據(jù)庫過程中,往往要修改其表中的數(shù)據(jù),比如往表中添加新數(shù)據(jù),刪除表中原有數(shù)據(jù),或?qū)Ρ碇性袛?shù)據(jù)進(jìn)行更改。它們的基本語法如下:?
數(shù)據(jù)添加:?
insert [into] table_name [(column(s))]?
values (expression(s))?
例:?
mysql> INSERT INTO tbl_name (col1,col2) VALUES(15,col1*2);?
數(shù)據(jù)刪除:?
刪除 from table_name where search_condition?
數(shù)據(jù)更改:?
更新 table_name?
set column1=expression1,?
column2=expression2,…?
where search_condition?

7.?dāng)?shù)據(jù)庫切換?
當(dāng)存在多個數(shù)據(jù)庫時,可以用下面的命令定義用戶想使用的數(shù)據(jù)庫:?
use database_name?

8.統(tǒng)計函數(shù)?
SQL有一些統(tǒng)計函數(shù),它們對于生成數(shù)據(jù)表格很有幫助。下面介紹幾個常用的統(tǒng)計函數(shù):?
sum (exepression) 計算表達(dá)式的和?
avg (exepression) 計算表達(dá)式的平均值?
count (exepression) 對表達(dá)式進(jìn)行簡單的計數(shù)?
count (*) 統(tǒng)計記錄數(shù)?
max (exepression) 求最大值?
min (exepression) 求最小值?
其中exepression為任何有效的SQL表達(dá)式,它可以是一個或多個記錄,也可以是別的SQL函數(shù)的組合。?

二、MySQL使用導(dǎo)引?
1.運用MySQL建立新數(shù)據(jù)庫?
在shell下運行:?
$>mysqladmin create database01?
Database "database01" created.?

2.啟動MySQL?
在shell下運行:?
$>mysql?
Welcome to the MySQL monitor. Commands end with ; or g.?
Your MySQL connection id is 22 to server version: 3.21. 29a-gamma-debug?
無效 ’help’ for help.?

3.更換數(shù)據(jù)庫?
mysql>use database01?
database changed.?

4.創(chuàng)建表?
mysql>create table table01 (field01 integer, field02 char(10));?
Query OK, 0 rows affected (0.00 sec)?

5.列出表清單?
mysql>show tables;?
Tables in database01?
Table01?
table02?

6.列出表中的字段清單?
mysql>show columns from table01;?
Field 無效 Null Key Default Extra?
field01 int(11) YES?
field02 char(10) YES?

7.表的數(shù)據(jù)填寫?
插入數(shù)據(jù)?
mysql>insert into table01 (field01, field02) values (1, ’first’);?
Query OK, 1 row affected (0.00 sec)?

8.字段的增加?
...一次一個字段?
mysql>alter table table01 add column field03 char(20);?
Query OK, l row affected (0.04 sec)?
Records: 1 Duplicates: 0 Warnings: 0?
...一次多個字段?
mysql>alter table table01 add column field04 date, add column field05 time;?
Query OK, l row affected (0.04 sec)?
Records: 1 Duplicates: 0 Warnings: 0?
注意:每一列都必須以"add column"重新開始。?
它運行了嗎?讓我們看看。?
mysql>select * from table01;?
field01 field02 field03 field04 field05?
1 first NULL NULL NULL?

9.多行命令輸入?
MySQL命令行界面允許把陳述作為一行輸入,也可以把它展開為多行輸入。這兩者之間并沒有語法上的區(qū)別。使用多行輸入,你可以將SQL陳述一步步分解,從而使你更容易理解。?
在多行方式下,注釋器把每一行都添加到前面的行后,直到你用分號";"來結(jié)束這個SQL陳述。一旦鍵入分號并按回車鍵,這個陳述即被執(zhí)行。?
下面的例子是同一個嚴(yán)格的SQL陳述的兩種輸入方法:?
單行輸入?
Mysql>create table table33 (field01 integer, field02 char(30));?
多行輸入?
Mysql>create table table33?
->(field01?
->integer,?
->field02?
->char(30));?
注意不能將單詞斷開,如:?
正確?
mysql>create table table33?
->( field01?
->integer,?
->field02?
->char(30));?
錯誤?
mysql>create table table33?
->( field01 inte?
->ger,?
->field02?
->char(30));?
當(dāng)插入或更改數(shù)據(jù)時,不能將字段的字符串展開到多行里,否則硬回車將被儲存到數(shù)據(jù)中:?
標(biāo)準(zhǔn)操作?
mysql>insert into table33 (field02)?
->values?
->(’who thought of foo?’);?
硬回車儲存到數(shù)據(jù)中?
mysql>insert into table33 (field02)?
->values?
->(’who thought?
->of foo?’);?
結(jié)果如下:?
mysql>select * from table33;?
field01 field02?
NULL who thought of foo??
NULL who thought?
Of foo??

10.表的數(shù)據(jù)嵌入?
mysql>insert into table01 (field01, field02, field03, field04, field05) values?
->(2, ’second’, ’another’, ’1999-10-23’, ’10:30:00’);?
Query OK, 1 row affected (0.00 sec)?
標(biāo)準(zhǔn)日期格式是"yyyy-mm-dd"。?
標(biāo)準(zhǔn)時間格式是"hh:mm:ss"。?
引號內(nèi)要求所給的是上述的標(biāo)準(zhǔn)日期和時間格式。?
日期也可以"yyyymmdd"形式,時間也可以"hhmmss"形式輸入,但其值不需要再加引號。?
數(shù)字值不需要加引號。這種保存與數(shù)據(jù)類型無關(guān),這些數(shù)據(jù)類型都有格式化的專欄來包含(例如:文本,日期,時間,整數(shù)等)。?
MySQL有一個很有用的命令緩沖區(qū)。它保存著你目前已經(jīng)鍵入的SQL語句利用它,對于相同的命令,你就不必一遍又一遍地重復(fù)輸入。下一步我們就來看這樣的一個例子。?
利用命令緩沖區(qū)(及任意的日期和時間格式)增加另一個數(shù)據(jù)?
按兩次鍵盤上的向上箭頭鍵。?
回車。?
在圓括號內(nèi)輸入新的值,并以分號結(jié)尾。?
(3, ’a third’, ’more’, 19991024, 103004);?
回車。?
新值存在里面了嗎??
mysql>select * from table01;?
field01 field02 field03 field04 field05?
1 first NULL NULL NULL?
2 second another 1999-10-23 10:30:00?
3 a third more 1999-10-24 10:30:04?

11.表的數(shù)據(jù)更新?
一次修改一個字段?
再次注意語法。文本需要加引號但數(shù)字不要。?
mysql>更新 table01 set field03=’new info’ where field01=1;?
Query OK, 1 row affected (0.00 sec)?
一次改變多個字段?
記住在每一個更新的字段間用逗號隔開。?
mysql>更新 table01 set field04=19991022, field05=062218 where field01=1;?
Query OK, 1 row affected (0.00 sec)?
一次更新多個數(shù)據(jù)?
mysql>更新 table01 set field05=152901 where field04>19990101;?
Query OK, 3 rows affected (0.00 sec)?

12.刪除數(shù)據(jù)?
mysql>刪除 from table01 where field01=3;?
Query OK, 1 row affected (0.00 sec)?

13.退出?
mysql>quit?
Bye?
現(xiàn)在你已經(jīng)了解了一些運行MySQL中的數(shù)據(jù)庫的根本命令。由于MySQL是通過執(zhí)行SQL調(diào)用來操作的,在你的處理過程中需要一個強有力工具的充足的數(shù)組。例如,通過聯(lián)接相關(guān)的字段,你可以同時顯示幾個表中的數(shù)據(jù)。同樣,SQL允許綜合顯示、更新或者刪除多個符合具體標(biāo)準(zhǔn)的數(shù)據(jù)。如果你還想精通掌握它,下一步就要學(xué)習(xí)所有SQL的知識。



semovy 2006-10-21 17:24 發(fā)表評論
]]>
學(xué)習(xí)MySQL多表操作和備份處理http://m.tkk7.com/WshmAndLily/articles/51388.htmlsemovysemovyThu, 08 Jun 2006 08:23:00 GMThttp://m.tkk7.com/WshmAndLily/articles/51388.htmlhttp://m.tkk7.com/WshmAndLily/comments/51388.htmlhttp://m.tkk7.com/WshmAndLily/articles/51388.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/51388.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/51388.html多表操作

????在一個數(shù)據(jù)庫中,可能存在多個表,這些表都是相互關(guān)聯(lián)的。我們繼續(xù)使用前面的例子。前面建立的表中包含了員工的一些基本信息,如姓名、性別、出生日期、出生地。我們再創(chuàng)建一個表,該表用于描述員工所發(fā)表的文章,內(nèi)容包括作者姓名、文章標(biāo)題、發(fā)表日期。

????1、查看第一個表mytable的內(nèi)容:

mysql> select * from mytable; 
+----------+------+------------+-----------+ 
| name | sex | birth | birthaddr | 
+----------+------+------------+-----------+ 
| abccs |f | 1977-07-07 | china | 
| mary |f | 1978-12-12 | usa | 
| tom |m | 1970-09-02 | usa | 
+----------+------+------------+-----------+


????2、創(chuàng)建第二個表title(包括作者、文章標(biāo)題、發(fā)表日期):

mysql> create table title(writer varchar(20) not null, 
-> title varchar(40) not null, 
-> senddate date); 
&nbsp;&nbsp;&nbsp;&nbsp;向該表中填加記錄,最后表的內(nèi)容如下: 
<ccid_nobr>
<table width="400" border="1" cellspacing="0" cellpadding="2" 
 bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center">
<tr>
    <td bgcolor="e6e6e6" class="code" style="font-size:9pt">
    <pre><ccid_code>  mysql> select * from title; 
+--------+-------+------------+ 
| writer | title | senddate | 
+--------+-------+------------+ 
| abccs | a1 | 2000-01-23 | 
| mary | b1 | 1998-03-21 | 
| abccs | a2 | 2000-12-04 | 
| tom | c1 | 1992-05-16 | 
| tom | c2 | 1999-12-12 | 
+--------+-------+------------+ 
5 rows in set (0.00sec)


????3、多表查詢

????現(xiàn)在我們有了兩個表: mytable 和 title。利用這兩個表我們可以進(jìn)行組合查詢:
????例如我們要查詢作者abccs的姓名、性別、文章:

mysql> SELECT name,sex,title FROM mytable,title 
-> WHERE name=writer AND name=′abccs′; 
+-------+------+-------+ 
| name | sex | title | 
+-------+------+-------+ 
| abccs | f | a1 | 
| abccs | f | a2 | 
+-------+------+-------+


????上面例子中,由于作者姓名、性別、文章記錄在兩個不同表內(nèi),因此必須使用組合來進(jìn)行查詢。必須要指定一個表中的記錄如何與其它表中的記錄進(jìn)行匹配。

????注意:如果第二個表title中的writer列也取名為name(與mytable表中的name列相同)而不是writer時,就必須用mytable.name和title.name表示,以示區(qū)別。

????再舉一個例子,用于查詢文章a2的作者、出生地和出生日期:

mysql> select title,writer,birthaddr,birth from mytable,title 
-> where mytable.name=title.writer and title=′a2′; 
+-------+--------+-----------+------------+ 
| title | writer | birthaddr | birth | 
+-------+--------+-----------+------------+ 
| a2 | abccs | china | 1977-07-07 | 
+-------+--------+-----------+------------+


????修改和備份、批處理
????有時我們要對數(shù)據(jù)庫表和數(shù)據(jù)庫進(jìn)行修改和刪除,可以用如下方法實現(xiàn):

????1、增加一列:
????如在前面例子中的mytable表中增加一列表示是否單身single:
????mysql> alter table mytable add column single char(1);

????2、修改記錄
????將abccs的single記錄修改為“y”:
????mysql> update mytable set single=′y′ where name=′abccs′; ????現(xiàn)在來看看發(fā)生了什么:

mysql> select * from mytable; 
+----------+------+------------+-----------+--------+ 
| name | sex | birth | birthaddr | single | 
+----------+------+------------+-----------+--------+ 
| abccs |f | 1977-07-07 | china | y | 
| mary |f | 1978-12-12 | usa | NULL | 
| tom |m | 1970-09-02 | usa | NULL | 
+----------+------+------------+-----------+--------+


????3、增加記錄
????前面已經(jīng)講過如何增加一條記錄,為便于查看,重復(fù)與此:

mysql> insert into mytable 
-> values (′abc′,′f′,′1966-08-17′,′china′,′n′); 
Query OK, 1 row affected (0.05 sec)


查看一下:

mysql> select * from mytable; 
+----------+------+------------+-----------+--------+ 
| name | sex | birth | birthaddr | single | 
+----------+------+------------+-----------+--------+ 
| abccs |f | 1977-07-07 | china | y | 
| mary |f | 1978-12-12 | usa | NULL | 
| tom |m | 1970-09-02 | usa | NULL | 
| abc |f | 1966-08-17 | china | n | 
+----------+------+------------+-----------+--------+


????4、刪除記錄
????用如下命令刪除表中的一條記錄:mysql> delete from mytable where name=′abc′;
????DELETE從表中刪除滿足由where給出的條件的一條記錄。
????再顯示一下結(jié)果:

mysql> select * from mytable; 
+----------+------+------------+-----------+--------+ 
| name | sex | birth | birthaddr | single | 
+----------+------+------------+-----------+--------+ 
| abccs |f | 1977-07-07 | china | y | 
| mary |f | 1978-12-12 | usa | NULL | 
| tom |m | 1970-09-02 | usa | NULL | 
+----------+------+------------+-----------+--------+


????5、刪除表:
????mysql> drop table ****(表1的名字),***表2的名字;
????可以刪除一個或多個表,小心使用。

????6、數(shù)據(jù)庫的刪除:
????mysql> drop database 數(shù)據(jù)庫名;
????小心使用。

????7、數(shù)據(jù)庫的備份:
????退回到DOS:
????mysql> quit
????d:mysqlbin

????使用如下命令對數(shù)據(jù)庫abccs進(jìn)行備份:
????mysqldump --opt abccs>abccs.dbb
????abccs.dbb就是你的數(shù)據(jù)庫abccs的備份文件。

????8、用批處理方式使用MySQL:

????首先建立一個批處理文件mytest.sql,內(nèi)容如下:

use abccs; 
select * from mytable; 
select name,sex from mytable where name=′abccs′;


????在DOS下運行如下命令:d:mysqlbin mysql < mytest.sql

????在屏幕上會顯示執(zhí)行結(jié)果。

????如果想看結(jié)果,而輸出結(jié)果很多,則可以用這樣的命令: mysql < mytest.sql | more

????我們還可以將結(jié)果輸出到一個文件中: mysql < mytest.sql > mytest.out

semovy 2006-06-08 16:23 發(fā)表評論
]]>
學(xué)習(xí)MySQL常用操作命令http://m.tkk7.com/WshmAndLily/articles/51386.htmlsemovysemovyThu, 08 Jun 2006 08:19:00 GMThttp://m.tkk7.com/WshmAndLily/articles/51386.htmlhttp://m.tkk7.com/WshmAndLily/comments/51386.htmlhttp://m.tkk7.com/WshmAndLily/articles/51386.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/51386.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/51386.html1、啟動MySQL服務(wù)器

????實際上上篇已講到如何啟動MySQL。兩種方法: 一是用winmysqladmin,如果機(jī)器啟動時已自動運行,則可直接進(jìn)入下一步操作。 二是在DOS方式下運行 d:mysqlbinmysqld

????2、進(jìn)入mysql交互操作界面

????在DOS方式下,運行: d:mysqlbinmysql

????出現(xiàn): mysql 的提示符,此時已進(jìn)入mysql的交互操作方式。

????如果出現(xiàn) "ERROR 2003: Can′t connect to MySQL server on ′localhost′ (10061)“,

說明你的MySQL還沒有啟動。

????3、退出MySQL操作界面

????在mysql>提示符下輸入quit可以隨時退出交互操作界面:
????mysql> quit
????Bye
????你也可以用control-D退出。

????4、第一條命令

mysql> select version(),current_date(); 
+----------------+-----------------+ 
| version() | current_date() | 
+----------------+-----------------+ 
| 3.23.25a-debug | 2001-05-17 | 
+----------------+-----------------+ 
1 row in set (0.01 sec) 
mysql>


????此命令要求mysql服務(wù)器告訴你它的版本號和當(dāng)前日期。嘗試用不同大小寫操作上述命令,看結(jié)果如何。結(jié)果說明mysql命令的大小寫結(jié)果是一致的。

????練習(xí)如下操作:

mysql>Select (20+5)*4; 
mysql>Select (20+5)*4,sin(pi()/3); 
mysql>Select (20+5)*4 AS Result,sin(pi()/3); (AS: 指定假名為Result) 
&nbsp;&nbsp;&nbsp;&nbsp;<B>5、多行語句</B> 
&nbsp;&nbsp;&nbsp;&nbsp;一條命令可以分成多行輸入,直到出現(xiàn)分號“;”為止: 
<ccid_nobr>
<table width="400" border="1" cellspacing="0" cellpadding="2" 
 bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center">
<tr>
    <td bgcolor="e6e6e6" class="code" style="font-size:9pt">
    <pre><ccid_code>  mysql> select 
-> USER() 
-> , 
-> now() 
->; 
+--------------------+---------------------+ 
| USER() | now() | 
+--------------------+---------------------+ 
| ODBC@localhost | 2001-05-17 22:59:15 | 
+--------------------+---------------------+ 
1 row in set (0.06 sec) 
mysql>


????注意中間的逗號和最后的分號的使用方法。

????6、一行多命令

????輸入如下命令:

mysql> SELECT USER(); SELECT NOW(); 
+------------------+ 
| USER() | 
+------------------+ 
| ODBC@localhost | 
+------------------+ 
1 row in set (0.00 sec) 

+---------------------+ 
| NOW() | 
+---------------------+ 
| 2001-05-17 23:06:15 | 
+---------------------+ 
1 row in set (0.00 sec) 
mysql>


????注意中間的分號,命令之間用分號隔開。

????7、顯示當(dāng)前存在的數(shù)據(jù)庫

mysql> show databases; 
+----------+ 
| Database | 
+----------+ 
| mysql | 
| test | 
+----------+ 
2 row in set (0.06 sec) 
mysql>


????8、選擇數(shù)據(jù)庫并顯示當(dāng)前選擇的數(shù)據(jù)庫

mysql> USE mysql 
Database changed 
mysql> 
(USE 和 QUIT 命令不需要分號結(jié)束。) 
mysql> select database(); 
+---------------+ 
| database() | 
+---------------+ 
| mysql | 
+---------------+ 
1 row in set (0.00 sec)


????9、顯示當(dāng)前數(shù)據(jù)庫中存在的表
????mysql> SHOW TABLES;

????10、顯示表(db)的內(nèi)容
mysql>select * from db;

????11、命令的取消

????當(dāng)命令輸入錯誤而又無法改變(多行語句情形)時,只要在分號出現(xiàn)前就可以用 c來取消該條命令

mysql> select 
-> user() 
-> c 
mysql>


????這是一些最常用的最基本的操作命令,通過多次練習(xí)就可以牢牢掌捂了。


semovy 2006-06-08 16:19 發(fā)表評論
]]>
MySQL安全性指南http://m.tkk7.com/WshmAndLily/articles/51382.htmlsemovysemovyThu, 08 Jun 2006 08:03:00 GMThttp://m.tkk7.com/WshmAndLily/articles/51382.htmlhttp://m.tkk7.com/WshmAndLily/comments/51382.htmlhttp://m.tkk7.com/WshmAndLily/articles/51382.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/51382.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/51382.html
本文主要考慮下列安全性有關(guān)的問題:

為什么安全性很重要,你應(yīng)該防范那些攻擊?
服務(wù)器面臨的風(fēng)險(內(nèi)部安全性),如何處理?
連接服務(wù)器的客戶端風(fēng)險(外部安全性),如何處理?
MySQL管理員有責(zé)任保證數(shù)據(jù)庫內(nèi)容的安全性,使得這些數(shù)據(jù)記錄只能被那些正確授權(quán)的用戶訪問,這涉及到數(shù)據(jù)庫系統(tǒng)的內(nèi)部安全性和外部安全性。
內(nèi)部安全性關(guān)心的是文件系統(tǒng)級的問題,即,防止MySQL數(shù)據(jù)目錄(DATADIR)被在服務(wù)器主機(jī)有賬號的人(合法或竊取的)進(jìn)行攻擊。如果數(shù)據(jù)目錄內(nèi)容的權(quán)限過分授予,使得每個人均能簡單地替代對應(yīng)于那些數(shù)據(jù)庫表的文件,那么確保控制客戶通過網(wǎng)絡(luò)訪問的授權(quán)表設(shè)置正確,對此毫無意義。

外部安全性關(guān)心的是從外部通過網(wǎng)絡(luò)連接服務(wù)器的客戶的問題,即,保護(hù)MySQL服務(wù)器免受來自通過網(wǎng)絡(luò)對服務(wù)器的連接的攻擊。你必須設(shè)置MySQL授權(quán)表(grant table),使得他們不允許訪問服務(wù)器管理的數(shù)據(jù)庫內(nèi)容,除非提供有效的用戶名和口令。

下面就詳細(xì)介紹如何設(shè)置文件系統(tǒng)和授權(quán)表mysql,實現(xiàn)MySQL的兩級安全性。


一、內(nèi)部安全性-保證數(shù)據(jù)目錄訪問的安全
MySQL服務(wù)器通過在MySQL數(shù)據(jù)庫中的授權(quán)表提供了一個靈活的權(quán)限系統(tǒng)。你可以設(shè)置這些表的內(nèi)容,允許或拒絕客戶對數(shù)據(jù)庫的訪問,這提供了你防止未授權(quán)的網(wǎng)絡(luò)訪問對你數(shù)據(jù)庫攻擊的安全手段,然而如果主機(jī)上其他用戶能直接訪問數(shù)據(jù)目錄內(nèi)容,建立對通過網(wǎng)絡(luò)訪問數(shù)據(jù)庫的良好安全性對你毫無幫助,除非你知道你是登錄MySQL服務(wù)器運行主機(jī)的唯一用戶,否則你需要關(guān)心在這臺機(jī)器上的其他用戶獲得對數(shù)據(jù)目錄的訪問的可能性。

以下是你應(yīng)該保護(hù)的內(nèi)容:

數(shù)據(jù)庫文件。很明顯,你要維護(hù)服務(wù)器管理的數(shù)據(jù)庫的私用性。數(shù)據(jù)庫擁有者通常并且應(yīng)該考慮數(shù)據(jù)庫內(nèi)容的安全性,即使他們不想,也應(yīng)該考慮時數(shù)據(jù)庫內(nèi)容公開化,而不是通過糟糕的數(shù)據(jù)目錄的安全性來暴露這些內(nèi)容。
日志文件。一般和更新日志必須保證安全,因為他們包含查詢文本。對日志文件有訪問權(quán)限的任何人可以監(jiān)視數(shù)據(jù)庫進(jìn)行過的操作。
更要重點考慮的日志文件安全性是諸如GRANT和SET PASSWORD等的查詢也被記載了,一般和更新日志包含有敏感查詢的文本,包括口令(MySQL使用口令加密,但它在已經(jīng)完成設(shè)置后才運用于以后的連接建立。設(shè)置一個口令的過程設(shè)計象GRANT或SET PASSWORD等查詢,并且這些查詢以普通文本形式記載在日志文件中)。如果一個攻擊者猶如日文件的讀權(quán)限,只需在日志文件上運行g(shù)rep尋找諸如GRANT和PASSWORD等詞來發(fā)現(xiàn)敏感信息。
顯然,你不想讓服務(wù)器主機(jī)上的其他用戶有數(shù)據(jù)庫目錄文件的寫權(quán)限,因為他們可以重寫你的狀態(tài)文件或數(shù)據(jù)庫表文件,但是讀權(quán)限也很危險。如果一個數(shù)據(jù)庫表文件能被讀取,偷取文件并得到MySQL本身,以普通文本顯示表的內(nèi)容也很麻煩,為什么?因為你要做下列事情:

在服務(wù)器主機(jī)上安裝你自己“特制”的MySQL服務(wù)器,但是有一個不同于官方服務(wù)器版本的端口、套接字和數(shù)據(jù)目錄。
運行mysql_install_db初始化你的數(shù)據(jù)目錄,這賦予你作為MySQL root用戶訪問你的服務(wù)器的權(quán)限,所以你有對服務(wù)器訪問機(jī)制的完全控制,它也建立一個test數(shù)據(jù)庫。
將對應(yīng)于你想偷取得表文件拷貝到你服務(wù)器的數(shù)據(jù)庫目錄下的test目錄。
啟動你的服務(wù)器。你可以隨意訪問數(shù)據(jù)庫表,SHOW TABLES FROM test顯示你有一個偷來的表的拷貝,SELECT *顯示它們?nèi)魏我粋€的全部內(nèi)容。
如果你確實很惡毒,將權(quán)限公開給你服務(wù)器的任何匿名用戶,這樣任何人能從任何地方連接服務(wù)器訪問你的test數(shù)據(jù)庫。你現(xiàn)在將偷來的數(shù)據(jù)庫表公布于眾了。
在考慮一下,從相反的角度,你想讓別人對你這樣嗎?當(dāng)然不!你可以通過在數(shù)據(jù)庫錄下執(zhí)行l(wèi)s -l命令確定你的數(shù)據(jù)庫是否包含不安全的文件和目錄。查找有“組”和“其他用戶”權(quán)限設(shè)置的文件和目錄。下面是一個不安全數(shù)據(jù)目錄的一部分列出:

 
% ls -l
total 10148
drwxrwxr-x??11??mysqladm wheel????1024 May??8 12:20
drwxr-xr-x??22??root?????wheel?????512 May??8 13:31 ..
drwx------???2??mysqladm mysqlgrp??512 Apr 16 15:57 menagerie
drwxrwxr-x???2??mysqladm wheel?????512 Jan 25 20:40 mysql
drwxrwxr-x???7??mysqladm wheel?????512 Aug 31??1998 sql-bench
drwxrwxr-x???2??mysqladm wheel????1536 May??6 06:11 test
drwx------???2??mysqladm mysqlgrp 1024 May??8 18:43 tmp
....


正如你看到的,有些數(shù)據(jù)庫有正確的權(quán)限,而其他不是。本例的情形是經(jīng)過一段時間后的結(jié)果。較少限制的權(quán)限由在權(quán)限設(shè)置方面比更新版本更不嚴(yán)格的較早版本服務(wù)器設(shè)置的(注意更具限制的目錄menageria和tmp都有較近日期)。MySQL當(dāng)前版本確保這些文件只能由運行服務(wù)器的用戶讀取。

讓我們來修正這些權(quán)限,使得只用服務(wù)器用戶可訪問它們。你的主要保護(hù)工具來自于由UNIX文件系統(tǒng)本身提供的設(shè)置文件和目錄屬主和模式的工具。下面是我們要做的:

進(jìn)入該目錄
% cd DATADIR

設(shè)置所有在數(shù)據(jù)目錄下的文件屬主為由用于運行服務(wù)器的賬號擁有(你必須以root執(zhí)行這步)。在本文使用mysqladm和mysqlgrp作為該賬號的用戶名和組名。你可以使用下列命令之一改變屬主:
# chown mysqladm.mysqlgrp .

# find . -follow -type d -print | xargs chown mysqladm.mysqlgrp

設(shè)置你的數(shù)據(jù)目錄和數(shù)據(jù)庫目錄的模式使得他們只能由mysqladm讀取,這阻止其他用戶訪問你數(shù)據(jù)庫目錄的內(nèi)容。你可以用下列命令之一以root或mysqladm身份運行。
% chmod -R go-rwx??.

% find . -follow -type d -print | xargs chmod go-rwx

數(shù)據(jù)目錄內(nèi)容的屬主和模式為mysqladm設(shè)置。現(xiàn)在你應(yīng)該保證你總是以mysqladm用戶運行服務(wù)器,因為現(xiàn)在這是唯一由訪問數(shù)據(jù)庫目錄權(quán)限的用戶(除root)。
在完成這些設(shè)置后,你最終應(yīng)該得到下面的數(shù)據(jù)目錄權(quán)限:

% ls -l
total 10148
drwxrwx---??11??mysqladm mysqlgrp 1024 May??8 12:20 .
drwxr-xr-x??22??root?????wheel?????512 May??8 13:31 ..
drwx------???2??mysqladm mysqlgrp??512 Apr 16 15:57 menagerie
drwx------???2??mysqladm mysqlgrp??512 Jan 25 20:40 mysq
drwx------???7??mysqladm mysqlgrp??512 Aug 31??1998 sql-bench
drwx------???2??mysqladm mysqlgrp 1536 May??6 06:11 test
drwx------???2??mysqladm mysqlgrp 1024 May??8 18:43 tmp
....



二、外部安全性-保證網(wǎng)絡(luò)訪問的安全
MySQL的安全系統(tǒng)是很靈活的,它允許你以多種不同方式設(shè)置用戶權(quán)限。一般地,你可使用標(biāo)準(zhǔn)的SQL語句GRANT和REVOKE語句做,他們?yōu)槟阈薷目刂瓶蛻粼L問的授權(quán)表,然而,你可能由一個不支持這些語句的老版本的MySQL(在3.22.11之前這些語句不起作用),或者你發(fā)覺用戶權(quán)限看起來不是以你想要的方式工作。對于這種情況,了解MySQL授權(quán)表的結(jié)構(gòu)和服務(wù)器如何利用它們決定訪問權(quán)限是有幫助的,這樣的了解允許你通過直接修改授權(quán)表增加、刪除或修改用戶權(quán)限,它也允許你在檢查這些表時診斷權(quán)限問題。

關(guān)于如何管理用戶賬號,見《MySQL的用戶管理》。而對GRANT和REVOKE語句詳細(xì)描述,見《MySQL參考手冊》。
2.1 MySQL授權(quán)表的結(jié)構(gòu)和內(nèi)容
通過網(wǎng)絡(luò)連接服務(wù)器的客戶對MySQL數(shù)據(jù)庫的訪問由授權(quán)表內(nèi)容來控制。這些表位于mysql數(shù)據(jù)庫中,并在第一次安裝MySQL的過程中初始化(運行mysql_install_db腳本)。授權(quán)表共有5個表:user、db、host、tables_priv和columns_priv。

表1 user、db和host授權(quán)表結(jié)構(gòu)
訪問范圍列

user db host
Host Host Host
User Db Db
Password User??
數(shù)據(jù)庫/表權(quán)限列
Alter_priv Alter_priv Alter_priv
Create_priv Create_priv Create_priv
Delete_priv Delete_priv Delete_priv
Drop_priv Drop_priv Drop_priv
Index_priv Index_priv Index_priv
Insert_priv Insert_priv Insert_priv
References_priv References_priv References_priv
Select_priv Select_priv Select_priv
Update_priv Update_priv Update_priv
File_priv Grant_priv Grant_priv
Grant_priv???
Process_priv???
Reload_priv???
Shutdown_priv???
 
表2 tables_priv和columns_priv屬權(quán)表結(jié)構(gòu)

訪問范圍列
tables_priv??columns_priv
Host??Host
Db??Db
User??User
Table_name??Table_name
Column_name???
權(quán)限列
Table_priv??Column_priv

授權(quán)表的內(nèi)容有如下用途:

user表
user表列出可以連接服務(wù)器的用戶及其口令,并且它指定他們有哪種全局(超級用戶)權(quán)限。在user表啟用的任何權(quán)限均是全局權(quán)限,并適用于所有數(shù)據(jù)庫。例如,如果你啟用了DELETE權(quán)限,在這里列出的用戶可以從任何表中刪除記錄,所以在你這樣做之前要認(rèn)真考慮。
db
db表列出數(shù)據(jù)庫,而用戶有權(quán)限訪問它們。在這里指定的權(quán)限適用于一個數(shù)據(jù)庫中的所有表。
host表
host表與db表結(jié)合使用在一個較好層次上控制特定主機(jī)對數(shù)據(jù)庫的訪問權(quán)限,這可能比單獨使用db好些。這個表不受GRANT和REVOKE語句的影響,所以,你可能發(fā)覺你根本不是用它。
tables_priv表
tables_priv表指定表級權(quán)限,在這里指定的一個權(quán)限適用于一個表的所有列。
columns_priv表
columns_priv表指定列級權(quán)限。這里指定的權(quán)限適用于一個表的特定列。
在“不用GRANT設(shè)置用戶”一節(jié)里,我們再討論GRANT語句如何對修改這些表起作用,和你怎樣能通過直接修改授權(quán)表達(dá)到同樣的效果。

tables_priv和columns_priv表在MySQL 3.22.11版引進(jìn)(與GRANT語句同時)。如果你有較早版本的MySQL,你的mysql數(shù)據(jù)庫將只有user、db和host表。如果你從老版本升級到3.22.11或更新,而沒有tables_priv和columns_priv表,運行mysql_fix_privileges_tables腳本創(chuàng)建它們。

MySQL沒有rows_priv表,因為它不提供記錄級權(quán)限,例如,你不能限制用戶于表中包含特定列值的行。如果你確實需要這種能力,你必須用應(yīng)用編程來提供。如果你想執(zhí)行建議的記錄級鎖定,你可用GET_LOCK()函數(shù)做到。

授權(quán)表包含兩種列:決定一個權(quán)限何時運用的范圍列和決定授予哪種權(quán)限的權(quán)限列。

2.1.1 授權(quán)表范圍列
授權(quán)表范圍列指定表中的權(quán)限何時運用。每個授權(quán)表條目包含User和Host列來指定權(quán)限何時運用于一個給定用戶從給定主機(jī)的連接。其他表包含附加的范圍列,如db表包含一個Db列指出權(quán)限運用于哪個數(shù)據(jù)庫。類似地,tables_priv和columns_priv表包含范圍字段,縮小范圍到一個數(shù)據(jù)庫中的特定表或一個表的特定列。

2.1.2 授權(quán)表權(quán)限列
授權(quán)表還包含權(quán)限列,他們指出在范圍列中指定的用戶擁有何種權(quán)限。由MySQL支持的權(quán)限如下表所示。該表使用GRANT語句的權(quán)限名稱。對于絕大多數(shù)在user、db和host表中的權(quán)限列的名稱與GRANT語句中有明顯的聯(lián)系。如Select_priv對應(yīng)于SELECT權(quán)限。

2.1.3 數(shù)據(jù)庫和表權(quán)限
下列權(quán)限運用于數(shù)據(jù)庫和表上的操作。

ALTER
允許你使用ALTER TABLE語句,這其實是一個簡單的第一級權(quán)限,你必須由其他權(quán)限,這看你想對數(shù)據(jù)庫實施什么操作。
CREATE
允許你創(chuàng)建數(shù)據(jù)庫和表,但不允許創(chuàng)建索引。
DELETE
允許你從表中刪除現(xiàn)有記錄。
DROP
允許你刪除(拋棄)數(shù)據(jù)庫和表,但不允許刪除索引。
INDEX
允許你創(chuàng)建并刪除索引。
REFERENCES
目前不用。
SELECT
允許你使用SELECT語句從表中檢索數(shù)據(jù)。對不涉及表的SELECT語句就不必要,如SELECT NOW()或SELECT 4/2。
UPDATE
允許你修改表中的已有的記錄。
2.1.4 管理權(quán)限
下列權(quán)限運用于控制服務(wù)器或用戶授權(quán)能力的操作的管理性操作。

FILE
允許你告訴服務(wù)器讀或?qū)懛?wù)器主機(jī)上的文件。該權(quán)限不應(yīng)該隨便授予,它很危險,見“回避授權(quán)表風(fēng)險”。服務(wù)器確實較謹(jǐn)慎地保持在一定范圍內(nèi)使用該權(quán)限。你只能讀任何人都能讀的文件。你正在寫的文件必須不是現(xiàn)存的文件,這防止你迫使服務(wù)器重寫重要文件,如/etc/passwd或?qū)儆趧e人的數(shù)據(jù)庫的數(shù)據(jù)目錄。
如果你授權(quán)FILE權(quán)限,確保你不以UNIX的root用戶運行服務(wù)器,因為root可在文件系統(tǒng)的任何地方創(chuàng)建新文件。如果你以一個非特權(quán)用戶運行服務(wù)器,服務(wù)器只能在給用戶能訪問的目錄中創(chuàng)建文件。

GRANT
允許你將你自己的權(quán)限授予別人,包括GRANT。
PROCESS
允許你通過使用SHOW PROCESS語句或mysqladmin process命令查看服務(wù)器內(nèi)正在運行的線程(進(jìn)程)的信息。這個權(quán)限也允許你用KILL語句或mysqladmin kill命令殺死線程。
你總是能看到或殺死你自己的線程。PROCESS權(quán)限賦予你對任何線程做這些事情的能力。

RELOAD
允許你執(zhí)行大量的服務(wù)器管理操作。你可以發(fā)出FLUSH語句,你也能指性mysqladmin的reload、refresh、flush-hosts、flush-logs、flush-privileges和flush-tables等命令。
SHUTDOWN
允許你用mysqladmin shutdown關(guān)閉服務(wù)器。
在user、db和host表中,每一個權(quán)限以一個單獨的列指定。這些列全部聲明為一個ENUM("N","Y")類型,所以每個權(quán)的缺省值是“N”。在tables_priv和columns_priv中的權(quán)限以一個SET表示,它允許權(quán)限用一個單個列以任何組合指定。這兩個表比其他三個表更新,這就是為什么它們使用更有效的表示方式的原因。(有可能在未來,user、db和host表也用一個SET類型表示。)

在tables_priv表中的Table_priv列被定義成:

SET('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter')
在coloums_priv表中的Column_priv列被定義成: 

SET('Select','Insert','Update','References')
列權(quán)限比表權(quán)限少,因為列級較少的權(quán)限有意義。例如你能創(chuàng)建一個表,但你不能創(chuàng)建一個孤立的列。

user表包含某些在其他授權(quán)表不存在的權(quán)限的列:File_priv、Process_priv、Reload_priv和Shutdown_priv。這些權(quán)限運用于你讓服務(wù)器執(zhí)行的與任何特定數(shù)據(jù)庫或表不相關(guān)的操作。如允許一個用戶根據(jù)當(dāng)前數(shù)據(jù)庫是什么來關(guān)閉數(shù)據(jù)庫是毫無意義的。

2.2 服務(wù)器如何控制客戶訪問
在你使用MySQL時,客戶訪問控制有兩個階段。第一階段發(fā)生在你試圖連接服務(wù)器時。服務(wù)器查找user表看它是否能找到一個條目匹配你的名字、你正在從那兒連接的主機(jī)和你提供的口令。如果沒有匹配,你就不能連接。如果有一個匹配,建立連接并繼續(xù)第二階段。在這個階段,對于每一個你發(fā)出的查詢,服務(wù)器檢查授權(quán)表看你是否有足夠的權(quán)限執(zhí)行查詢,第二階段持續(xù)到你與服務(wù)器對話的結(jié)束



本小節(jié)詳細(xì)介紹MySQL服務(wù)器用于將授權(quán)表條目匹配到來的連接請求或查詢的原則,這包括在授權(quán)表范圍列中合法的值的類型、結(jié)合授權(quán)表中的權(quán)限信息的方式和表中條目被檢查的次序。

2.2.1 范圍列內(nèi)容
一些范圍列要求文字值,但它們大多數(shù)允許通配符或其他特殊值。

Host
一個Host列值可以是一個主機(jī)名或一個IP地址。值localhost意味著本地主機(jī),但它只在你用一個localhost主機(jī)名時才匹配,而不是你在使用主機(jī)名時。假如你的本地主機(jī)名是pit.snake.net并且在user表中有對你的兩條記錄,一個有一個Host值或localhost,而另一個有pit.snake.net,有l(wèi)ocalhost的記錄將只當(dāng)你連接localhost時匹配,其他在只在連接pit.snake.net時才匹配。如果你想讓客戶能以兩種方式連接,你需要在user表中有兩條記錄。

你也可以用通配符指定Host值。可以使用SQL的模式字符“%”和“_”并具有當(dāng)你在一個查詢中使用LIKE算符同樣的含義(不允許regex算符)。 SQL模式字符都能用于主機(jī)名和IP地址。如%wisc.edu匹配任何wisc.edu域內(nèi)的主機(jī),而%.edu匹配任何教育學(xué)院的主機(jī)。類似地,192.168.%匹配任何在192.168 B類子網(wǎng)的主機(jī),而192.168.3.%匹配任何在192.168.3 C類子網(wǎng)的主機(jī)。

%值匹配所有主機(jī),并可用于允許一個用戶從任何地方連接。一個空白的Host值等同于%。(例外:在db表中,一個空白Host值含義是“進(jìn)一步檢查host表”,該過程在“查詢訪問驗證”中介紹。)

從MySQL 3.23起,你也可以指定帶一個表明那些為用于網(wǎng)絡(luò)地址的網(wǎng)絡(luò)掩碼的IP地址,如192.168.128.0/17指定一個17位網(wǎng)絡(luò)地址并匹配其IP地址是192.168128前17位的任何主機(jī)。

User
用戶名必須是文字的或空白。一個空白值匹配任何用戶。%作為一個User值不意味著空白,相反它匹配一個字面上的%名字,這可能不是你想要的。

當(dāng)一個到來的連接通過user表被驗證而匹配的記錄包含一個空白的User值,客戶被認(rèn)為是一個匿名用戶。

Password
口令值可以是空或非空,不允許用通配符。一個空口令不意味著匹配任何口令,它意味著用戶必須不指定口令。

口令以一個加密過的值存儲,不是一個字面上的文本。如果你在Password列中存儲一個照字面上的口令,用戶將不能連接!GRANT語句和mysqladmin password命令為你自動加密口令,但是如果你用諸如INSERT、REPLACE、UPDATE或SET PASSWORD等命令,一定要用PASSWORD("new_password")而不是簡單的"new_password"來指定口令。

Db
在columns_priv和tables_priv表中,Db值必須是真正的數(shù)據(jù)庫名(照字面上),不允許模式和空白。在db和host中,Db值可以以字面意義指定或使用SQL模式字符'%'或'_'指定一個通配符。一個'%'或空白匹配任何數(shù)據(jù)庫。
Table_name,Column_name
這些列中的值必須是照字面意思的表或列名,不允許模式和空白。
某些范圍列被服務(wù)器視為大小寫敏感的,其余不是。這些原則總結(jié)在下表中。特別注意Table_name值總是被看作大小寫敏感的,即使在查詢中的表名的大小寫敏感性對待視服務(wù)器運行的主機(jī)的文件系統(tǒng)而定(UNIX下是大小寫敏感,而Windows不是)。

表3 授權(quán)表范圍列的大小寫敏感性

Host
User
Password
Db
Table_name
Column_name
大小寫敏感性
No
Yes
Yes
Yes
Yes
No


2.2.2 查詢訪問驗證
每次你發(fā)出一個查詢,服務(wù)器檢查你是否有足夠的權(quán)限執(zhí)行它,它以user、db、tables_priv和columns_priv的順序檢查,知道它確定你有適當(dāng)?shù)脑L問權(quán)限或已搜索所有表而一無所獲。更具體的說:

服務(wù)器檢查user表匹配你開始連接的記錄以查看你有什么全局權(quán)限。如果你有并且它們對查詢足夠了,服務(wù)器則執(zhí)行它。


如果你的全局權(quán)限不夠,服務(wù)器為你在db表中尋找并將該記錄中的權(quán)限加到你的全局權(quán)限中。如果結(jié)果對查詢足夠,服務(wù)器執(zhí)行它。
如果你的全局和數(shù)據(jù)庫級組合的權(quán)限不夠,服務(wù)器繼續(xù)查找,首先在tables_priv表,然后columns_priv表。
如果你在檢查了所有表之后仍無權(quán)限,服務(wù)器拒絕你執(zhí)行查詢的企圖。
用布爾運算的術(shù)語,授權(quán)表中的權(quán)限被服務(wù)器這樣使用:

user OR tables_priv OR columns_priv

你可能疑惑為什么前面的描述只引用4個授權(quán)表,而實際上有5個。實際上服務(wù)器是這樣檢查訪問權(quán)限:

user OR (db AND host) OR tables_priv OR columns_priv

第一個較簡單的表達(dá)式是因為host表不受GRANT和REVOKE語句影響。如果你總是用GRANT和REVOKE管理用戶權(quán)限,你絕不需要考慮host表。但是其工作原理你用該知道:

當(dāng)服務(wù)器檢查數(shù)據(jù)庫級權(quán)限時,它對于客戶查找db表。如果Host列是空的,它意味著“檢查host表以找出哪一個主機(jī)能訪問數(shù)據(jù)庫”。
服務(wù)器在host表中查找有與來自db表的記錄相同的Db列值。如果沒有host記錄匹配客戶主機(jī),則沒有授予數(shù)據(jù)庫級權(quán)限。如果這些記錄的任何一個的確有一個匹配連接的客戶主機(jī)的Host列值,db表記錄和host表記錄結(jié)合產(chǎn)生客戶的數(shù)據(jù)庫級權(quán)限。
然而,權(quán)限用一個邏輯AND(與)結(jié)合起來,這意味著除非一個給定的權(quán)限在兩個表中都有,否則客戶就不具備該權(quán)限。以這種方式,你可以在db表中授予一個基本的權(quán)限集,然后使用host表對特定的主機(jī)有選擇地禁用它們。如你可以允許從你的域中的所有主機(jī)訪問數(shù)據(jù)庫,但關(guān)閉了那些在較不安全區(qū)域的主機(jī)的數(shù)據(jù)庫權(quán)限。

前面的描述毫無疑問使訪問檢查聽起來一個相當(dāng)復(fù)雜的過程,特別是你以為服務(wù)器對你發(fā)出的每個查詢進(jìn)行權(quán)限檢查,然而此過程是很快的,因為服務(wù)器其實不從授權(quán)表對每個查詢查找信息,相反,它在啟動時將表的內(nèi)容讀入內(nèi)存,然后驗證查詢用的是內(nèi)存中的副本。這大大提高了訪問檢查操作的性能。但有一個非常明顯的副作用。如果你直接修改授權(quán)表的內(nèi)容,服務(wù)器將不知道權(quán)限的改變。

例如,如果你用一條INSERT語句向user表加入一個新記錄來增加一個新用戶,命名在記錄中的用戶將不能連接服務(wù)器。這對管理員新手(有時對有經(jīng)驗的老手)是很困惑的事情,當(dāng)時解決方法很簡單:在你改變了它們之后告訴服務(wù)器重載授權(quán)表內(nèi)容,你可以發(fā)一條FLUSH PRIVILEGES或執(zhí)行mysqladmin flush-privileges(或如果你有一個不支持flush-privileges的老版本,用mysqladmin reload。)。

2.2.3 范圍列匹配順序
MySQL服務(wù)器按一種特定方式排序符授權(quán)表中的記錄,然后通過按序瀏覽記錄匹配到來的連接。找到的第一個匹配決定了被使用的記錄。理解MySQL使用的排序順序很重要,特別是對user表。

當(dāng)服務(wù)器讀取user表內(nèi)容時,它根據(jù)在Host和User列中的值排序記錄,Host值起決定作用(相同的Host值排在一起,然后再根據(jù)User值排序)。然而,排序不是典序(按詞排序),它只是部分是。要牢記的是字面上的詞優(yōu)先于模式。這意味著如果你正從client.your.net連接服務(wù)器而Host有client.your.net和%.your.net兩個值,則第一個先選。類似地,%.your.net優(yōu)先于%.net,然后是%。IP地址的匹配也是這樣的。

總之一句話,越具體越優(yōu)先。可以參見本文附錄的實例。

2.3 避免授權(quán)表風(fēng)險
本屆介紹一些在你授權(quán)時的一些預(yù)防措施,以及不明值的選擇帶來的風(fēng)險。一般地,你要很“吝嗇”地授予超級用戶權(quán)限,即不要啟用user表中條目中的權(quán)限,而使用其它授權(quán)表,以將用戶權(quán)限限制于數(shù)據(jù)庫、表、或列。在user表中的權(quán)限允許于影響到你的服務(wù)器操作或能訪問任何數(shù)據(jù)庫中的任何表。

不要授予對mysql數(shù)據(jù)庫的權(quán)限。一個擁有包含授權(quán)表數(shù)據(jù)庫權(quán)限的用戶可能會修改表以獲取對其他任何數(shù)據(jù)庫的權(quán)限。授予允許一個用戶修改mysql數(shù)據(jù)庫表的權(quán)限也實際上給了用戶以一個全局GRANT權(quán)限。如果用戶能直接修改表,這也等價于能夠發(fā)出任何你能想象的任何GRANT語句。

FILE權(quán)限尤其危險,不要輕易授權(quán)它。以下是一個擁有FILE權(quán)限的人能干除的事情:

????CREATE TABLE etc_passwd (pwd_entry TEXT)
????LOAD DATA INFILE "/etc/passwd" into TABLE etc_passwd;
????SELECT * FROM etc_passwd;
在發(fā)出這些語句后,用戶已經(jīng)擁有了你的口令文件的內(nèi)容了。實際上,服務(wù)器上任何公開可讀文件的內(nèi)容都可被擁有FILE權(quán)限的用戶通過網(wǎng)絡(luò)訪問。

FILE權(quán)限也能被利用來危害沒有設(shè)置足夠權(quán)限制的文件權(quán)限的系統(tǒng)上的數(shù)據(jù)庫。這就是你為什么應(yīng)該設(shè)置數(shù)據(jù)目錄只能由服務(wù)器讀取的原因。如果對應(yīng)于數(shù)據(jù)庫表的文件可被任何人讀取,不只是用戶服務(wù)器賬號的用戶可讀,任何有FILE權(quán)限的用戶也可通過網(wǎng)絡(luò)連接并讀取它們。下面演示這個過程:

創(chuàng)建一個有一個LONGBLOB列的表:
USER test;
CREATE TABLE tmp (b LONGBLOB);

使用該表讀取每個對應(yīng)于你想偷取的數(shù)據(jù)庫表文件的內(nèi)容,然后將表內(nèi)容寫入你自己數(shù)據(jù)庫的一個文件中:

LOAD DATA INFILE "./other_db/x.frm" INTO TABLE tmp
?????FIELDS ESCAPED BY "" LINES TERMINATED BY "";
SELECT * FROM tmp INTO OUTFILE "y.frm"
?????FIELDS ESCAPED BY "" LINES TERMINATED BY "";
DELETE FROM tmp;
LOAD DATA INFILE "./other_db/x.ISD" INTO TABLE tmp
?????FIELDS ESCAPED BY "" LINES TERMINATED BY "";
SELECT * FROM tmp INTO OUTFILE "y.ISD"
?????FIELDS ESCAPED BY "" LINES TERMINATED BY "";
DELETE FROM tmp;
LOAD DATA INFILE "./other_db/x.ISM" INTO TABLE tmp
?????FIELDS ESCAPED BY "" LINES TERMINATED BY "";
SELECT * FROM tmp INTO OUTFILE "y.ISM"
現(xiàn)在你擁有了一個新表y,它包含other_db.x的內(nèi)容并且你有全權(quán)訪問它。
為避免讓人以同樣的方式攻擊,根據(jù)“第一部分 內(nèi)部安全性-保護(hù)你的數(shù)據(jù)目錄”中的指令設(shè)置你的數(shù)據(jù)目錄上的權(quán)限。你也可以在你啟動服務(wù)器時使用--skip-show-database選項限制用戶對于他們沒用訪問權(quán)限的數(shù)據(jù)庫使用SHOW DATABASES和SHOW TABLES。這有助于防止用戶找到關(guān)于它們不能訪問的數(shù)據(jù)庫和表的信息。

ALTER權(quán)限能以不希望的方式使用。假定你想讓user1可以訪問table1但不能訪問tables2。一個擁有ALTER權(quán)限的用戶可以通過使用ALTER TABLE將table2改名為table1來偷梁換柱。

當(dāng)心GRANT權(quán)限。兩個由不同權(quán)限但都有GRANT權(quán)限的用戶可以使彼此的權(quán)利更強大。

2.4 不用GRANT設(shè)置用戶
如果你有一個早于3.22.11的MySQL版本,你不能使用GRANT(或REVOKE)語句設(shè)置用戶及其訪問權(quán)限,但你可以直接修改授權(quán)表的內(nèi)容。如果你理解GRANT語句如何修改授權(quán)表,這很容易。那么你通過手工發(fā)出INSERT語句就能自己做同樣的事情。

當(dāng)你發(fā)出一條GRANT語句時,你指定一個用戶名和主機(jī)名,可能還有口令。對該用戶生成一個user表記錄,并且這些值記錄在User、Host和Password列中。如果你在GRANT語句中指定全局權(quán)限,這些權(quán)限記錄在記錄的權(quán)限列中。其中要留神的是GRANT語句為你加密口令,而INSERT不是,你需要在INSERT中使用PASSWORD()函數(shù)加密口令。

如果你指定數(shù)據(jù)庫級權(quán)限,用戶名和主機(jī)名被記錄在db表的User和Host列。你為其授權(quán)的數(shù)據(jù)庫記錄在Db列中,你授予的權(quán)限記錄在權(quán)限列中。

對于表級和列級權(quán)限,效果是類似的。在tables_priv和columns_priv表中創(chuàng)建記錄以記錄用戶名、主機(jī)名和數(shù)據(jù)庫,還有相關(guān)的表和列。授予的權(quán)限記錄在權(quán)限列中。

如果你還記得前面的介紹,你應(yīng)該能即使不用GRANT語句也能做GRANT做的事情。記住在你直接修改授權(quán)表時,你將通知服務(wù)器重載授權(quán)表,否則他不知道你的改變。你可以執(zhí)行一個mysqladmin flush-privileges或mysqladmin reload命令強迫一個重載。如果你忘記做這個,你會疑惑為什么服務(wù)器不做你想做的事情。

下列GRANT語句創(chuàng)建一個擁有所有權(quán)的超級用戶。包括授權(quán)給別人的能力:

GRANT ALL ON *.* TO anyname@localhost IDENTIFIED BY "passwd"
????WITH GRANT OPTION
該語句將在user表中為anyname@localhost創(chuàng)建一個記錄,打開所有權(quán)限,因為這里是超級用戶(全局)權(quán)限存儲的地方,要用INSERT語句做同樣的事情,語句是:

INSERT INTO user??VALUES("localhost","anyname",PASSWORD("passwd"),
????"Y","Y","Y","Y","Y","Y","Y","Y","Y","Y","Y","Y","Y","Y")
你可能發(fā)現(xiàn)它不工作,這要看你的MySQL版本。授權(quán)表的結(jié)構(gòu)已經(jīng)改變而且你在你的user表可能沒有14個權(quán)限列。用SHOW COLUMNS找出你的授權(quán)表包含的每個權(quán)限列,相應(yīng)地調(diào)整你的INSERT語句。 下列GRANT語句也創(chuàng)建一個擁有超級用戶身份的用戶,但是只有一個單個的權(quán)限:

GRANT RELOAD ON *.* TO flush@localhost IDENTIFIED BY "flushpass"
本例的INSERT語句比前一個簡單,它很容易列出列名并只指定一個權(quán)限列。所有其它列將設(shè)置為缺省的"N":

INSERT INTO user (Host,Password,Reload) VALUES("localhost","flush",PASSWORD("flushpass"),"Y")
數(shù)據(jù)庫級權(quán)限用一個ON db_name.*子句而不是ON *.*進(jìn)行授權(quán):

GRANT ALL ON sample.* TO boris@localhost IDENTIFIED BY "ruby"
這些權(quán)限不是全局的,所以它們不存儲在user表中,我們?nèi)匀恍枰趗ser表中創(chuàng)建一條記錄(使得用戶能連接),但我們也需要創(chuàng)建一個db表記錄記錄數(shù)據(jù)庫集權(quán)限:
INSERT INTO user (Host,User,Password) VALUES("localhost","boris",PASSWORD("ruby"))

INSERT INTO db VALUES("localhost","sample_db","boris","Y","Y","Y","Y","Y","Y","N","Y","Y","Y")

"N"列是為GRANT權(quán)限;對末尾的一個數(shù)據(jù)庫級具有WITH GRANT OPTION的GRANT語句,你要設(shè)置該列為"Y"。

要設(shè)置表級或列級權(quán)限,你對tables_priv或columns_priv使用INSERT語句。當(dāng)然,如果你沒有GRANT語句,你將沒有這些表,因為它們在MySQL中同時出現(xiàn)。如果你確實有這些表并且為了某些原因想要手工操作它們,要知道你不能用單獨的列啟用權(quán)限。

你設(shè)置tables_priv.Table_priv或columns_priv.Column_priv列來設(shè)置包含你想啟用的權(quán)限值。例如,要對一個表啟用SELECT和INSERT權(quán)限,你要在相關(guān)的tables_priv的記錄中設(shè)置Table_priv為"Select,Insert"。

如果你想對一個擁有MySQL賬號的用戶修改權(quán)限,使用UPDATE而不是INSERT,不管你增加或撤銷權(quán)限都是這樣。要完全刪除一個用戶,從用戶使用的每個表中刪除記錄。

如果你愿意避免發(fā)一個查詢來直接修改全權(quán)表,你可以看一下MySQL自帶的mysqlaccess和mysql_setpermissions腳本。



附錄1 小測驗
在你剛剛新安裝了一個MySQL服務(wù)器,在你增加了一個允許連接MySQL的用戶,用下列語句:

GRANT ALL ON samp_db.* TO fred@*.snake.net IDENTIFIED "cocoa"

而fred碰巧在服務(wù)器主機(jī)上有個賬號,所以他試圖連接服務(wù)器:

%mysql -u fred -pcocoa samp_db
ERROR 1045: Access denied for user: 'fred@localhost' (Using password: YES)

為什么?

原因是:

先考慮一下mysql_install_db如何建立初始權(quán)限表和服務(wù)器如何使用user表記錄匹配客戶連接。在你用mysql_install_db初始化你的數(shù)據(jù)庫時,它創(chuàng)建類似這樣的user表:

Host User
localhost
pit.snake.net
localhost
pit.snake.net root
root



頭兩個記錄允許root指定localhost或主機(jī)名連接本地服務(wù)器,后兩個允許匿名用戶從本地連接。當(dāng)增加fred用戶后,

Host User
localhost
pit.snake.net
localhost
pit.snake.net
%.snake.net root
root


fred

在服務(wù)器啟動時,它讀取記錄并排序它們(首先按主機(jī),然后按主機(jī)上的用戶),越具體越排在前面:

Host User
localhost
localhost
pit.snake.net
pit.snake.net
%.snake.net root

root

fred

有l(wèi)ocalhost的兩個記錄排在一起,而對root的記錄排在第一,因為它比空值更具體。pit.snake.net的記錄也類似。所有這些均是沒有任何通配符的字面上的Host值,所以它們排在對fred記錄的前面,特別是匿名用戶排在fred之前
結(jié)果是在fred試圖從localhost連接時,Host列中的一個空用戶名的記錄在包含%.snake.net的記錄前匹配。該記錄的口令是空的,因為缺省的匿名用戶沒有口令。因為在fred連接時指定了一個口令,由一個錯配且連接失敗。

這里要記住的是,雖然用通配符指定用戶可以從其連接的主機(jī)是很方便。但你從本地主機(jī)連接時會有問題,只要你在table表中保留匿名用戶記錄。
一般地,建議你刪除匿名用戶記錄:

mysql> DELETE FROM user WHERE User="";

更進(jìn)一步,同時刪除其他授權(quán)表中的任何匿名用戶,有User列的表有db、tables_priv和columns_priv。

附錄2 使一個新的MySQL安裝更安全
在你自己安裝了一個新的MySQL服務(wù)器后,你需要為MySQL的root用戶指定一個目錄(缺省無口令),否則如果你忘記這點,你將你的MySQL處于極不安全的狀態(tài)(至少在一段時間內(nèi))。

在Unix(Linux)上,在按照手冊的指令安裝好MySQL后,你必須運行mysql_install_db腳本建立包含授權(quán)表的mysql數(shù)據(jù)庫和初始權(quán)限。在Windows上,運行分發(fā)中的Setup程序初始化數(shù)據(jù)目錄和mysql數(shù)據(jù)庫。假定服務(wù)器也在運行。

當(dāng)你第一次在機(jī)器上安裝MySQL時,mysql數(shù)據(jù)庫中的授權(quán)表是這樣初始化的:

你可以從本地主機(jī)(localhost)上以root連接而不指定口令。root用戶擁有所有權(quán)限(包括管理權(quán)限)并可做任何事情。(順便說明,MySQL超級用戶與Unix超級用戶有相同的名字,他們彼此毫無關(guān)系。)
匿名訪問被授予用戶可從本地連接名為test和任何名字以test_開始的數(shù)據(jù)庫。匿名用戶可對數(shù)據(jù)庫做任何事情,但無管理權(quán)限。
從本地主機(jī)多服務(wù)器的連接是允許的,不管連接的用戶使用一個localhost主機(jī)名或真實主機(jī)名。如:

% mysql -h localhost test

% mysql -h pit.snake.net test

你以root連接MySQL甚至不指定口令的事實只是意味著初始安裝不安全,所以作為管理員的你首先要做的應(yīng)該是設(shè)置root口令,然后根據(jù)你設(shè)置口令使用的方法,你也可以告訴服務(wù)器重載授權(quán)表是它知道這個改變。(在服務(wù)器啟動時,它重載表到內(nèi)存中而可能不知道你已經(jīng)修改了它們。)

對MySQL 3.22和以上版本,你可以用mysqladmin設(shè)置口令:

% mysqladmin -u root password yourpassword

對于MySQL的任何版本,你可以用mysql程序并直接修改mysql數(shù)據(jù)庫中的user授權(quán)表:

% mysql -u root mysql
mysql>UPDATE user SET password=PASSWORD("yourpassword") WHERE User="root";

如果你有MySQL的老版本,使用mysql和UPDATE。

在你設(shè)置完口令后,通過運行下列命令檢查你是否需要告訴服務(wù)器重載授權(quán)表:

% mysqladmin -u root status

如果服務(wù)器仍然讓你以root而不指定口令而連接服務(wù)器,重載授權(quán)表:

% mysqladmin -u root reload

在你設(shè)置了root的口令后(并且如果需要重載了授權(quán)表),你將需要在任何時候以root連接服務(wù)器時指定口令。


semovy 2006-06-08 16:03 發(fā)表評論
]]>
MySQL數(shù)據(jù)庫SQL語法參考http://m.tkk7.com/WshmAndLily/articles/51374.htmlsemovysemovyThu, 08 Jun 2006 07:45:00 GMThttp://m.tkk7.com/WshmAndLily/articles/51374.htmlhttp://m.tkk7.com/WshmAndLily/comments/51374.htmlhttp://m.tkk7.com/WshmAndLily/articles/51374.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/51374.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/51374.html
  資料定語言是指對資料的格式和形態(tài)下定義的語言,他是每個資料庫要建立時候時首先要面對的,舉凡資料分哪些表格關(guān)系、表格內(nèi)的有什麼欄位主鍵、表格和表格之間互相參考的關(guān)系等等,都是在開始的時候所必須規(guī)劃好的。

  1、建表格:

create table table_name(
column1 datatype [not null] [not null primary key],
column2 datatype [not null],
...);

  說明: 

datatype --是資料的格式,詳見表。
nut null --可不可以允許資料有空的(尚未有資料填入)。
primary key --是本表的主鍵。

  2、更改表格 

alter table table_name
add column column_name datatype

  說明:增加一個欄位(沒有刪除某個欄位的語法。

alter table table_name
add primary key (column_name)

  說明:更改表得的定義把某個欄位設(shè)為主鍵。

alter table table_name
drop primary key (column_name)

  說明:把主鍵的定義刪除。

  3、建立索引 

create index index_name on table_name (column_name)

  說明:對某個表格的欄位建立索引以增加查詢時的速度。

  4、刪除 

drop table_name
drop index_name

  二、資料操作 dml (data manipulation language)

  資料定義好之後接下來的就是資料的操作。資料的操作不外乎增加資料(insert)、查詢資料(query)、更改資料(update) 、刪除資料(delete)四種模式,以下分 別介紹他們的語法:

  1、增加資料:

insert into table_name (column1,column2,...)
values ( value1,value2, ...)

  說明:

  1.若沒有指定column 系統(tǒng)則會按表格內(nèi)的欄位順序填入資料。

  2.欄位的資料形態(tài)和所填入的資料必須吻合。

  3.table_name 也可以是景觀 view_name。

insert into table_name (column1,column2,...)
select columnx,columny,... from another_table

  說明:也可以經(jīng)過一個子查詢(subquery)把別的表格的資料填入。

  2、查詢資料:

  基本查詢

select column1,columns2,...
from table_name

  說明:把table_name 的特定欄位資料全部列出來

select *
from table_name
where column1 = xxx
[and column2 > yyy] [or column3 <> zzz]

  說明:

  1.'*'表示全部的欄位都列出來。

  2.where 之後是接條件式,把符合條件的資料列出來。

select column1,column2
from table_name
order by column2 [desc]

  說明:order by 是指定以某個欄位做排序,[desc]是指從大到小排列,若沒有指明,則是從小到大

  排列

  組合查詢

  組合查詢是指所查詢得資料來源并不只有單一的表格,而是聯(lián)合一個以上的表格才能夠得到結(jié)果的。

select *
from table1,table2
where table1.colum1=table2.column1

  說明:

  1.查詢兩個表格中其中 column1 值相同的資料。

  2.當(dāng)然兩個表格相互比較的欄位,其資料形態(tài)必須相同。

  3.一個復(fù)雜的查詢其動用到的表格可能會很多個。

  整合性的查詢:

select count (*)
from table_name
where column_name = xxx

  說明:

  查詢符合條件的資料共有幾筆。

select sum(column1)
from table_name

  說明:

  1.計算出總和,所選的欄位必須是可數(shù)的數(shù)字形態(tài)。

  2.除此以外還有 avg() 是計算平均、max()、min()計算最大最小值的整合性查詢。

select column1,avg(column2)
from table_name
group by column1
having avg(column2) > xxx

  說明:

  1.group by: 以column1 為一組計算 column2 的平均值必須和 avg、sum等整合性查詢的關(guān)鍵字一起使用。

  2.having : 必須和 group by 一起使用作為整合性的限制。

  復(fù)合性的查詢

select *
from table_name1
where exists (
select *
from table_name2
where conditions )

  說明:

  1.where 的 conditions 可以是另外一個的 query。

  2.exists 在此是指存在與否。

select *
from table_name1
where column1 in (
select column1
from table_name2
where conditions )

  說明: 

  1. in 後面接的是一個集合,表示column1 存在集合里面。

  2. select 出來的資料形態(tài)必須符合 column1。

  其他查詢

select *
from table_name1
where column1 like 'x%'

  說明:like 必須和後面的'x%' 相呼應(yīng)表示以 x為開頭的字串。

select *
from table_name1
where column1 in ('xxx','yyy',..)

  說明:in 後面接的是一個集合,表示column1 存在集合里面。

select *
from table_name1
where column1 between xx and yy

  說明:between 表示 column1 的值介於 xx 和 yy 之間。

  3、更改資料:

update table_name
set column1='xxx'
where conditoins

  說明:

  1.更改某個欄位設(shè)定其值為'xxx'。

  2.conditions 是所要符合的條件、若沒有 where 則整個 table 的那個欄位都會全部被更改。

  4、刪除資料:

delete from table_name
where conditions

  說明:刪除符合條件的資料。

  說明:關(guān)于where條件后面如果包含有日期的比較,不同數(shù)據(jù)庫有不同的表達(dá)式。具體如下:

  (1)如果是Access數(shù)據(jù)庫,則為:where mydate>#2000-01-01#

  (2)如果是Oracle數(shù)據(jù)庫,則為:where mydate>cast('2000-01-01' as date) 或:where mydate>to_date('2000-01-01','yyyy-mm-dd')
Delphi中寫成:

thedate='2000-01-01';
query1.sql.add('select * from abc where mydate>cast('+''''+thedate+''''+' as date)');

  如果比較日期時間型,則為:

where mydatetime>to_date('2000-01-01 10:00:01','yyyy-mm-dd hh24:mi:ss');



semovy 2006-06-08 15:45 發(fā)表評論
]]>
mysql數(shù)據(jù)庫優(yōu)化五步走http://m.tkk7.com/WshmAndLily/articles/51373.htmlsemovysemovyThu, 08 Jun 2006 07:42:00 GMThttp://m.tkk7.com/WshmAndLily/articles/51373.htmlhttp://m.tkk7.com/WshmAndLily/comments/51373.htmlhttp://m.tkk7.com/WshmAndLily/articles/51373.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/51373.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/51373.html  
  2:硬盤的讀寫速度,這個速度非常的快,這個更容易解決--可以從多個硬盤上并行讀寫.
  
  3:cpu.cpu處理內(nèi)存中的數(shù)據(jù),當(dāng)有相對內(nèi)存較小的表時,這是最常見的限制因素.
  
  4:內(nèi)存的限制.當(dāng)cpu需要超出適合cpu緩存的數(shù)據(jù)時,緩存的帶寬就成了內(nèi)存的一個瓶頸---不過現(xiàn)在內(nèi)存大的驚人,一般不會出現(xiàn)這個問題.
  
  第二步: (本人使用的是學(xué)校網(wǎng)站的linux平臺(Linux ADVX.Mandrakesoft.com 2.4.3-19mdk ))
  

  1:調(diào)節(jié)服務(wù)器參數(shù)
  
  用shell>mysqld-help這個命令聲廠一張所有mysql選項和可配置變量的表.輸出以下信息:
  
  possible variables for option--set-variable(-o) are:
  
  back_log current value:5 //要求mysql能有的連接數(shù)量.back_log指出在mysql暫停接受連接的時間內(nèi)有多少個連接請求可以被存在堆棧中
  
  connect_timeout current value:5 //mysql服務(wù)器在用bad handshake(不好翻譯)應(yīng)答前等待一個連接的時間
  
  delayed_insert_timeout current value:200 //一個insert delayed在終止前等待insert的時間
  
  delayed_insert_limit current value:50 //insert delayed處理器將檢查是否有任何select語句未執(zhí)行,如果有,繼續(xù)前執(zhí)行這些語句
  
  delayed_queue_size current value:1000 //為insert delayed分配多大的隊
  
  flush_time current value:0 //如果被設(shè)置為非0,那么每個flush_time 時間,所有表都被關(guān)閉
  
  interactive_timeout current value:28800 //服務(wù)器在關(guān)上它之前在洋交互連接上等待的時間
  
  join_buffer_size current value:131072 //用與全部連接的緩沖區(qū)大小
  
  key_buffer_size current value:1048540 //用語索引塊的緩沖區(qū)的大小,增加它可以更好的處理索引
  
  lower_case_table_names current value:0 //
  
  long_query_time current value:10 //如果一個查詢所用時間大于此時間,slow_queried計數(shù)將增加
  
  max_allowed_packet current value:1048576 //一個包的大小
  
  max_connections current value:300 //允許同時連接的數(shù)量
  
  max_connect_errors current value:10 //如果有多于該數(shù)量的中斷連接,將阻止進(jìn)一步的連接,可以用flush hosts來解決
  
  max_delayed_threads current value:15 //可以啟動的處理insert delayed的數(shù)量
  
  max_heap_table_size current value:16777216 //
  
  max_join_size current value:4294967295 //允許讀取的連接的數(shù)量
  
  max_sort_length current value:1024 //在排序blob或者text時使用的字節(jié)數(shù)量
  
  max_tmp_tables current value:32 //一個連接同時打開的臨時表的數(shù)量
  
  max_write_lock_count current value:4294967295 //指定一個值(通常很小)來啟動mysqld,使得在一定數(shù)量的write鎖定之后出現(xiàn)read鎖定
  
  net_buffer_length current value:16384 //通信緩沖區(qū)的大小--在查詢時被重置為該大小
  
  query_buffer_size current value:0 //查詢時緩沖區(qū)大小
  
  record_buffer current value:131072 //每個順序掃描的連接為其掃描的每張表分配的緩沖區(qū)的大小
  
  sort_buffer current value:2097116 //每個進(jìn)行排序的連接分配的緩沖區(qū)的大小
  
  table_cache current value:64 //為所有連接打開的表的數(shù)量
  
  thread_concurrency current value:10 //
  
  tmp_table_size current value:1048576 //臨時表的大小
  
  thread_stack current value:131072 //每個線程的大小
  
  wait_timeout current value:28800 //服務(wù)器在關(guān)閉它3之前的一個連接上等待的時間
  
  根據(jù)自己的需要配置以上信息會對你幫助.
  第三:
  
  1:如果你在一個數(shù)據(jù)庫中創(chuàng)建大量的表,那么執(zhí)行打開,關(guān)閉,創(chuàng)建(表)的操作就會很慢. 2:mysql使用內(nèi)存
  
  a: 關(guān)鍵字緩存區(qū)(key_buffer_size)由所有線程共享
  
  b: 每個連接使用一些特定的線程空間.一個棧(默認(rèn)為64k,變量thread_stack),一個連接緩沖區(qū)(變量net_buffer_length)和一個結(jié)果緩沖區(qū)(net_buffer_length).特定情況下,連接緩沖區(qū)和結(jié)果緩沖區(qū)被動態(tài)擴(kuò)大到max_allowed_packet.
  
  c:所有線程共享一個基存儲器
  
  d:沒有內(nèi)存影射
  
  e:每個做順序掃描的請求分配一個讀緩沖區(qū)(record_buffer)
  
  f:所有聯(lián)結(jié)均有一遍完成并且大多數(shù)聯(lián)結(jié)甚至可以不用一個臨時表完成.最臨時的表是基于內(nèi)存的(heap)表
  
  g:排序請求分配一個排序緩沖區(qū)和2個臨時表
  
  h:所有語法分析和計算都在一個本地存儲器完成
  
  i:每個索引文件只被打開一次,并且數(shù)據(jù)文件為每個并發(fā)運行的線程打開一次
  
  j:對每個blob列的表,一個緩沖區(qū)動態(tài)的被擴(kuò)大以便讀入blob值
  
  k:所有正在使用的表的表處理器被保存在一個緩沖器中并且作為一個fifo管理.
  
  l:一個mysqladmin flush-tables命令關(guān)閉所有不在使用的表并且在當(dāng)前執(zhí)行的線程結(jié)束時標(biāo)記所有在使用的表準(zhǔn)備關(guān)閉
  
  3:mysql鎖定表
  
  mysql中所有鎖定不會成為死鎖. wirte鎖定: mysql的鎖定原理:a:如果表沒有鎖定,那么鎖定;b否則,把鎖定請求放入寫鎖定隊列中
  
  read鎖定: mysql的鎖定原理:a:如果表沒有鎖定,那么鎖定;b否則,把鎖定請求放入讀鎖定隊列中
  
  有時候會在一個表中進(jìn)行很多的select,insert操作,可以在一個臨時表中插入行并且偶爾用臨時表的記錄更新真正的表
  
  a:用low_priority屬性給一個特定的insert,update或者delete較低的優(yōu)先級
  
  b:max_write_lock_count指定一個值(通常很小)來啟動mysqld,使得在一定數(shù)量的write鎖定之后出現(xiàn)read鎖定
  
  c:通過使用set sql_low_priority_updates=1可以從一個特定的線程指定所有的更改應(yīng)該由較低的優(yōu)先級完成
  
  d:用high_priority指定一個select
  
  e:如果使用insert....select....出現(xiàn)問題,使用myisam表------因為它支持因為它支持并發(fā)的select和insert
  
  4:最基本的優(yōu)化是使數(shù)據(jù)在硬盤上占據(jù)的空間最小.如果索引做在最小的列上,那么索引也最小.實現(xiàn)方法:
  
  a:使用盡可能小的數(shù)據(jù)類型
  
  b:如果可能,聲明表列為NOT NULL.
  
  c:如果有可能使用變成的數(shù)據(jù)類型,如varchar(但是速度會受一定的影響)
  
  d:每個表應(yīng)該有盡可能短的主索引 e:創(chuàng)建確實需要的索引
  
  f:如果一個索引在頭幾個字符上有唯一的前綴,那么僅僅索引這個前綴----mysql支持在一個字符列的一部分上的索引
  
  g:如果一個表經(jīng)常被掃描,那么試圖拆分它為更多的表
  
  第四步
  
  1:索引的使用,索引的重要性就不說了,功能也不說了,只說怎么做. 首先要明確所有的mysql索引(primary,unique,index)在b樹中有存儲.索引主要用語:
  
  a:快速找到where指定條件的記錄 b:執(zhí)行聯(lián)結(jié)時,從其他表檢索行 c:對特定的索引列找出max()和min()值
  
  d:如果排序或者分組在一個可用鍵的最前面加前綴,排序或分組一個表
  
  e:一個查詢可能被用來優(yōu)化檢索值,而不用訪問數(shù)據(jù)文件.如果某些表的列是數(shù)字型并且正好是某個列的前綴,為了更快,值可以從索引樹中取出
  
  2:存儲或者更新數(shù)據(jù)的查詢速度  grant的執(zhí)行會稍稍的減低效率.
  
  mysql的函數(shù)應(yīng)該被高度的優(yōu)化.可以用benchmark(loop_count,expression)來找出是否查詢有問題
  
  select的查詢速度:如果想要讓一個select...where...更快,我能想到的只有建立索引.可以在一個表上運行myisamchk--analyze來更好的優(yōu)化查詢.可以用myisamchk--sort-index--sort-records=1來設(shè)置用一個索引排序一個索引和數(shù)據(jù).
  
  3:mysql優(yōu)化where子句
  
  3.1:刪除不必要的括號:
  
  ((a AND b) AND c OR (((a AND b) AND (a AND d))))>(a AND b AND c) OR (a AND b AND c AND d)
  
  3.2:使用常數(shù)
  
  (ab>5 AND b=c AND a=5
  
  3.3:刪除常數(shù)條件
  
  (b>=5 AND b=5) OR (b=6 AND 5=5) OR (b=100 AND 2=3) >b=5 OR b=6
  
  3.4:索引使用的常數(shù)表達(dá)式僅計算一次
  
  3.5:在一個表中,沒有一個where的count(*)直接從表中檢索信息
  
  3.6:所有常數(shù)的表在查詢中在任何其他表之前讀出
  
  3.7:對外聯(lián)結(jié)表最好聯(lián)結(jié)組合是嘗試了所有可能性找到的
  
  3.8:如果有一個order by字句和一個不同的group by子句或者order by或者group by包含不是來自聯(lián)結(jié)的第一個表的列,那么創(chuàng)建一個臨時表
  
  3.9:如果使用了sql_small_result,那么msyql使用在內(nèi)存中的一個表
  
  3.10:每個表的索引給查詢并且使用跨越少于30%的行的索引.
  
  3.11在每個記錄輸出前,跳過不匹配having子句的行
4:優(yōu)化left join
  
  在mysql中 a left join b按以下方式實現(xiàn)
  
  a:表b依賴于表a 
  
  b:表a依賴于所有用在left join條件的表(除了b)
  
  c:所有l(wèi)eft join條件被移到where子句中
  
  d:進(jìn)行所有的聯(lián)結(jié)優(yōu)化,除了一個表總是在所有他依賴的表后讀取.如果有一個循環(huán)依賴,那么將發(fā)生錯誤
  
  e:進(jìn)行所有的標(biāo)準(zhǔn)的where優(yōu)化 f:如果在a中有一行匹配where子句,但是在b中沒有任何匹配left join條件,那么,在b中生成的所有設(shè)置為NULL的一行
  
  g:如果使用left join來找出某些表中不存在的行并且在where部分有column_name IS NULL測試(column_name為NOT NULL列).那么,mysql在它已經(jīng)找到了匹配left join條件的一行后,將停止在更多的行后尋找
  
  5:優(yōu)化limit
  
  a:如果用limit只選擇一行,當(dāng)mysql需要掃描整個表時,它的作用相當(dāng)于索引
  
  b:如果使用limit#與order by,mysql如果找到了第#行,將結(jié)束排序,而不會排序正個表
  
  c:當(dāng)結(jié)合limit#和distinct時,mysql如果找到了第#行,將停止
  
  d:只要mysql已經(jīng)發(fā)送了第一個#行到客戶,mysql將放棄查詢
  
  e:limit 0一直會很快的返回一個空集合.
  
  f:臨時表的大小使用limit#計算需要多少空間來解決查詢
  
  6:優(yōu)化insert
  
  插入一條記錄的是由以下構(gòu)成:
  
  a:連接(3)
  
  b:發(fā)送查詢給服務(wù)器(2)
  
  c:分析查詢(2)
  
  d:插入記錄(1*記錄大小)
  
  e:插入索引(1*索引)
  
  f:關(guān)閉(1)
  
  以上數(shù)字可以看成和總時間成比例
  
  改善插入速度的一些方法:
  
  6.1:如果同時從一個連接插入許多行,使用多個值的insert,這比用多個語句要快
  
  6.2:如果從不同連接插入很多行,使用insert delayed語句速度更快
  
  6.3: 用myisam,如果在表中沒有刪除的行,能在select:s正在運行的同時插入行
  
  6.4: 當(dāng)從一個文本文件裝載一個表時,用load data infile.這個通常比insert快20 倍
  
  6.5:可以鎖定表然后插入--主要的速度差別是在所有insert語句完成后,索引緩沖區(qū)僅被存入到硬盤一次.一般與有不同的insert語句那樣多次存入要快.如果能用一個單個語句插入所有的行,鎖定就不需要.鎖定也降低連接的整體時間.但是對某些線程最大等待時間將上升.例如:
  
  thread 1 does 1000 inserts
  
  thread 2,3 and 4 does 1 insert
  
  thread 5 does 1000 inserts
  
  如果不使用鎖定,2,3,4將在1和5之前完成.如果使用鎖定,2,3,4,將可能在1和5之后完成.但是整體時間應(yīng)該快40%.因為insert,update,delete操作在mysql中是很快的,通過為多于大約5次連續(xù)不斷的插入或更新一行的東西加鎖,將獲得更好的整體性能.如果做很多一行的插入,可以做一個lock tables,偶爾隨后做一個unlock tables(大約每1000行)以允許另外的線程存取表.這仍然將導(dǎo)致獲得好的性能.load data infile對裝載數(shù)據(jù)仍然是很快的.
  
  為了對load data infile和insert得到一些更快的速度,擴(kuò)大關(guān)鍵字緩沖區(qū).
  
  7優(yōu)化update的速度
  
  它的速度依賴于被更新數(shù)據(jù)的大小和被更新索引的數(shù)量
  
  使update更快的另一個方法是推遲修改,然后一行一行的做很多修改.如果鎖定表,做一行一行的很多修改比一次做一個快
  
  8優(yōu)化delete速度
  
  刪除一個記錄的時間與索引數(shù)量成正比.為了更快的刪除記錄,可以增加索引緩存的大小 從一個表刪除所有行比刪除這個表的大部分要快的多
  
  第五步
  
  1:選擇一種表類型 1.1靜態(tài)myisam
  
  這種格式是最簡單且最安全的格式,它是磁盤格式中最快的.速度來自于數(shù)據(jù)能在磁盤上被找到的難易程度.當(dāng)鎖定有一個索引和靜態(tài)格式的東西是,它很簡單,只是行長度乘以數(shù)量.而且在掃描一張表時,每次用磁盤讀取來讀入常數(shù)個記錄是很容易的.安全性來源于如果當(dāng)寫入一個靜態(tài)myisam文件時導(dǎo)致計算機(jī)down掉,myisamchk很容易指出每行在哪里開始和結(jié)束,因此,它通常能收回所有記錄,除了部分被寫入的記錄.在mysql中所有索引總能被重建
  
  1.2動態(tài)myisam
  
  這種格式每一行必須有一個頭說明它有多長.當(dāng)一個記錄在更改期間變長時,它可以在多于一個位置上結(jié)束.能使用optimize tablename或myisamchk整理一張表.如果在同一個表中有像某些varchar或者blob列那樣存取/改變的靜態(tài)數(shù)據(jù),將動態(tài)列移入另外一個表以避免碎片.
  
  1.2.1壓縮myisam,用可選的myisampack工具生成
1.2.2內(nèi)存
  
  這種格式對小型/中型表很有用.對拷貝/創(chuàng)建一個常用的查找表到洋heap表有可能加快多個表聯(lián)結(jié),用同樣數(shù)據(jù)可能要快好幾倍時間.
  
  select tablename.a,tablename2.a from tablename,tablanem2,tablename3 where
  
  tablaneme.a=tablename2.a and tablename2.a=tablename3.a and tablename2.c!=0;
  
  為了加速它,可以用tablename2和tablename3的聯(lián)結(jié)創(chuàng)建一個臨時表,因為用相同列(tablename1.a)查找.
  
  CREATE TEMPORARY TABLE test TYPE=HEAP
  
  SELECT
  
  tablename2.a as a2,tablename3.a as a3
  
  FROM
  
  tablenam2,tablename3
  
  WHERE
  
  tablename2.a=tablename3.a and c=0;
  
  SELECT tablename.a,test.a3 from tablename,test where tablename.a=test.a1;
  
  SELECT tablename.a,test,a3,from tablename,test where tablename.a=test.a1 and ....;
  
  1.3靜態(tài)表的特點
  
  1.3.1默認(rèn)格式.用在表不包含varchar,blob,text列的時候
  
  1.3.2所有的char,numeric和decimal列填充到列寬度
  
  1.3.3非常快
  
  1.3.4容易緩沖
  
  1.3.5容易在down后重建,因為記錄位于固定的位置
  
  1.3.6不必被重新組織(用myisamchk),除非是一個巨量的記錄被刪除并且優(yōu)化存儲大小
  
  1.3.7通常比動態(tài)表需要更多的存儲空間
  
  1.4動態(tài)表的特點
  
  1.4.1如果表包含任何varchar,blob,text列,使用該格式
  
  1.4.2所有字符串列是動態(tài)的
  
  1.4.3每個記錄前置一個位.
  
  1.4.4通常比定長表需要更多的磁盤空間
  
  1.4.5每個記錄僅僅使用所需要的空間,如果一個記錄變的很大,它按需要被分成很多段,這導(dǎo)致了記錄碎片
  
  1.4.6如果用超過行長度的信息更新行,行被分段.
  
  1.4.7在系統(tǒng)down掉以后不好重建表,因為一個記錄可以是多段
  
  1.4.8對動態(tài)尺寸記錄的期望行長度是3+(number of columns+7)/8+(number of char columns)+packed size of numeric columns+length of strings +(number of NULL columns+7)/8
  
  對每個連接有6個字節(jié)的懲罰.無論何時更改引起記錄的變大,都有一個動態(tài)記錄被連接.每個新連接至少有20個字節(jié),因此下一個變大將可能在同一個連接中.如果不是,將有另外一個連接.可以用myisamchk -惡毒檢查有多少連接.所有連接可以用myisamchk -r刪除.
  
  1.5壓縮表的特點
  
  1.5.1一張用myisampack實用程序制作的只讀表.
  
  1.5.2解壓縮代碼存在于所有mysql分發(fā)中,以便使沒有myisampack的連接也能讀取用myisampack壓縮的表
  
  1.5.3占據(jù)很小的磁盤空間
  
  1.5.4每個記錄被單獨壓縮.一個記錄的頭是一個定長的(1~~3個字節(jié))這取決于表的最大記錄.每列以不同的方式被壓縮.一些常用的壓縮類型是:
  
  a:通常對每列有一張不同的哈夫曼表  b:后綴空白壓縮  c:前綴空白壓縮 d:用值0的數(shù)字使用1位存儲
  
  e:如果整數(shù)列的值有一個小范圍,列使用最小的可能類型來存儲.例如:如果所有的值在0到255之間,一個bigint可以作為一個tinyint存儲
  
  g:如果列僅有可能值的一個小集合,列類型被轉(zhuǎn)換到enum  h:列可以使用上面的壓縮方法的組合
  
  1.5.5能處理定長或動態(tài)長度的記錄,去不能處理blob或者text列 1.5.6能用myisamchk解壓縮
  
  mysql能支持不同的索引類型,但一般的類型是isam,這是一個B樹索引并且能粗略的為索引文件計算大小為(key_length+4)*0.67,在所有的鍵上的總和.
  
  字符串索引是空白壓縮的。如果第一個索引是一個字符串,它可將壓縮前綴如果字符串列有很多尾部空白或是一個總部能甬道全長的varchar列,空白壓縮使索引文件更小.如果很多字符串有相同的前綴.
  
  1.6內(nèi)存表的特點
  
  mysql內(nèi)部的heap表使用每偶溢出去的100%動態(tài)哈希并且沒有與刪除有關(guān)的問題.只能通過使用在堆表中的一個索引來用等式存取東西(通常用'='操作符)
  
  堆表的缺點是:
  
  1.6.1想要同時使用的所有堆表需要足夠的額外內(nèi)存
  
  1.6.2不能在索引的一個部分搜索
  
  1.6.3不能按順序搜索下一個條目(即,使用這個索引做一個order by)
  
  1.6.4mysql不能算出在2個值之間大概有多少行.這被優(yōu)化器使用是用來決定使用哪個索引的,但是在另一個方面甚至不需要磁盤尋道

semovy 2006-06-08 15:42 發(fā)表評論
]]>
數(shù)據(jù)庫人員手邊系列:Mysql字段長度http://m.tkk7.com/WshmAndLily/articles/51370.htmlsemovysemovyThu, 08 Jun 2006 07:37:00 GMThttp://m.tkk7.com/WshmAndLily/articles/51370.htmlhttp://m.tkk7.com/WshmAndLily/comments/51370.htmlhttp://m.tkk7.com/WshmAndLily/articles/51370.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/51370.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/51370.html列類型 需要的存儲量
  
  TINYINT 1 字節(jié)
  
  SMALLINT 2 個字節(jié)
  
  MEDIUMINT 3 個字節(jié)
  
  INT 4 個字節(jié)
  
  INTEGER 4 個字節(jié)
  
  BIGINT 8 個字節(jié)
  
  FLOAT(X) 4 如果 X < = 24 或 8 如果 25 < = X < = 53
  
  FLOAT 4 個字節(jié)
  
  DOUBLE 8 個字節(jié)
  
  DOUBLE PRECISION 8 個字節(jié)
  
  REAL 8 個字節(jié)
  
  DECIMAL(M,D) M字節(jié)(D+2 , 如果M < D)
  
  NUMERIC(M,D) M字節(jié)(D+2 , 如果M < D)
  
  日期和時間類型
  
  列類型 需要的存儲量
  
  DATE 3 個字節(jié)
  
  DATETIME 8 個字節(jié)
  
  TIMESTAMP 4 個字節(jié)
  
  TIME 3 個字節(jié)
  
  YEAR 1 字節(jié)
  
  串類型
  
  列類型 需要的存儲量
  
  CHAR(M) M字節(jié),1 <= M <= 255
  
  VARCHAR(M) L+1 字節(jié), 在此L <= M和1 <= M <= 255
  
  TINYBLOB, TINYTEXT L+1 字節(jié), 在此L< 2 ^ 8
  
  BLOB, TEXT L+2 字節(jié), 在此L< 2 ^ 16
  
  MEDIUMBLOB, MEDIUMTEXT L+3 字節(jié), 在此L< 2 ^ 24
  
  LONGBLOB, LONGTEXT L+4 字節(jié), 在此L< 2 ^ 32
  
  ENUM('value1','value2',...) 1 或 2 個字節(jié), 取決于枚舉值的數(shù)目(最大值65535)
  
  SET('value1','value2',...) 1,2,3,4或8個字節(jié), 取決于集合成員的數(shù)量(最多64個成員)

semovy 2006-06-08 15:37 發(fā)表評論
]]>
關(guān)于Mysql 4.1語言問題的完美解決方法http://m.tkk7.com/WshmAndLily/articles/51369.htmlsemovysemovyThu, 08 Jun 2006 07:34:00 GMThttp://m.tkk7.com/WshmAndLily/articles/51369.htmlhttp://m.tkk7.com/WshmAndLily/comments/51369.htmlhttp://m.tkk7.com/WshmAndLily/articles/51369.html#Feedback0http://m.tkk7.com/WshmAndLily/comments/commentRss/51369.htmlhttp://m.tkk7.com/WshmAndLily/services/trackbacks/51369.html可以不需要修改my.ini。在建立數(shù)據(jù)庫的時候,對庫和表的字符集設(shè)置不太重要,但是對文本類型的字段最好都設(shè)置為GBK字符集。

??? 對于已有的數(shù)據(jù)庫可以用以下方法轉(zhuǎn)換字段編碼:

??? ALTER TABLE t MODIFY hoverfly BINARY(100);

??? ALTER TABLE t MODIFY hoverfly CHAR(100) CHARACTER SET gbk;

??? 注意用此方法如果不修改程序,會發(fā)現(xiàn)查詢出的結(jié)果都是亂碼,可以通過在my.ini的[mysqld]段內(nèi)加default-character-set=gbk來糾正。但是這樣你會發(fā)現(xiàn)那些沒有轉(zhuǎn)換編碼的文本字段里的中文都是亂碼。

??? 其實有更簡單的辦法,在進(jìn)行查詢前,只要執(zhí)行SET character_set_results = NULL就可以。而且這是不管是轉(zhuǎn)換了的還是沒轉(zhuǎn)換的字段都不會出現(xiàn)亂碼。而轉(zhuǎn)換了的字段可以正常的對中文進(jìn)行排序。



semovy 2006-06-08 15:34 發(fā)表評論
]]>
主站蜘蛛池模板: 亚洲av无码一区二区乱子伦as| 亚洲综合av一区二区三区不卡| 国产偷国产偷亚洲清高APP| 亚欧免费一级毛片| 免费午夜爽爽爽WWW视频十八禁| 4480yy私人影院亚洲| 九九视频高清视频免费观看| 亚洲欧洲免费无码| 亚洲精品线在线观看| kk4kk免费视频毛片| 国产一级淫片a免费播放口之| 亚洲妓女综合网99| 男人进去女人爽免费视频国产| 亚洲精品99久久久久中文字幕 | 亚洲人成色99999在线观看| 外国成人网在线观看免费视频| 亚洲区小说区图片区| 亚洲AV电影天堂男人的天堂| 黄色网址免费观看| 亚洲一区免费观看| 两个人日本WWW免费版| 亚洲精品第一国产综合精品99| 亚洲AV成人片无码网站| 最新仑乱免费视频| 亚洲制服丝袜在线播放| 无码一区二区三区免费| 精品亚洲综合在线第一区| 一级做a爰性色毛片免费| 又爽又高潮的BB视频免费看| 亚洲老熟女五十路老熟女bbw| 国产精品久久久久久久久免费| 亚洲AV日韩精品久久久久久久| 97在线视频免费公开视频| 亚洲日韩中文字幕日韩在线| 美女视频黄频a免费| 国产精品久久久久影院免费| 亚洲午夜福利在线视频| 成人免费视频网址| 亚洲欧洲无码AV不卡在线| 成年人视频在线观看免费| 亚洲AV无码专区在线亚|