總網頁瀏覽量

顯示具有 資料庫 標籤的文章。 顯示所有文章
顯示具有 資料庫 標籤的文章。 顯示所有文章

2013年2月4日 星期一

Transaction--rollback與isolation等級實作

1. 啟動 SQL Server Management Studio, 登入 SQL Server,
   新增查詢, 執行下列指令:
print @@SPID
得到連線id 55

2.去"活動監視器"

3.接著回到查詢部分,下以下指令
begin transaction
select * from Customers
  where CompanyName Like 'B%'
print 'trans count: ' + Convert(varchar(4), @@TranCount)//印出目前有幾筆交易,因為SQL沒有自動轉字串功能所以要將int的TranCount轉成字串。

4.結束交易
commit transaction
print 'trans count: ' + Convert(varchar(4), @@TranCount)

(PS:如果commit transaction前面有指令錯誤的話,SQL會強制取消交易,這時再印TranCount會是零)
(PS:如果有多筆交易,執行一次commit transaction只會結束掉一筆交易)


到這裡可以知道所謂的交易就是由begin transaction .....commit transaction包住的指令。而且還沒下達commit transaction指令,表示transaction尚未結束。

體驗交易處理的完整性與可回復性

5.

begin transaction
update Customers
  set CompanyName = 'Bottom-Dollar Markets 123'
  where CustomerID = 'BOTTM'//update 資料

select * from Customers
  where CompanyName Like 'B%'

此時發現 BOTTM的CompanyName的值已經變成Bottom-Dollar Markets 123


6.接著打上
rollback transaction
//這是取消交易的指令,並且回復到交易前的狀態

select * from Customers
  where CompanyName Like 'B%'
此時,BOTTM的CompanyName的值又變回Bottom-Dollar Markets

//切記已經commit的交易就無法再rollback了

Rollback原理:
利用一個暫時交易紀錄檔來回復異動資料,在transaction開始時,SQLserver會將要更改的資料一 鎖定並且進行更改,同時也會建立一個暫時交易紀錄檔,來存放交易中更改資料的過程及內容。
交易一旦被commit時,則會將暫時交易紀錄檔的內容儲存到資料庫的log檔中,使該項交易異動視為已完成。因此無法rollback回去了。除非使用備份還原功能。



體驗交易的隔離性(Isolation):

一、隔離等級為:read commted

1.開兩個查詢視窗

2.在第一個視窗(spid=55)

set transaction isolation level read committed
begin transaction
select * from Customers
  where CompanyName Like 'B%'


3.在第二個視窗(spid=58)

use northwind
update Customers
  set CompanyName = 'Blauer See Delikatessen 123'
  where CustomerID = 'BLAUS'

之後下指令select CompanyName from Customers where CustomerID='BLAUS'
可以知道在第一視窗進行隔離等級為read commited的交易之下
第二視窗仍可以更動資料,資料更新成功



4. 接著去第一視窗執行:
update Customers
  set CompanyName = 'Bottom-Dollar Markets 123'
  where CustomerID = 'BOTTM'

5.之後去第二視窗執行
select CompanyName from Customers where CustomerID='BOTTM'
這時候無法查詢到資料,因為第一視窗仍在交易進行中,將資料給鎖住(lock)。

打開活動監視器看處理序發現spid為55的源頭封鎖者的值為1,表示第一視窗將資料給鎖住。
再看看id為58的欄位,等候類型的值LCK_M_S ,封鎖者的值是55。

6.去第一視窗打上
rollback tran
這時第二視窗已經秀出查詢結果了。


read commited:第一視窗不允許第二視窗讀取(select)第一視窗正在更新(update)且尚未commit的資料,因此該資料後來被更動的機率就比較小(因為第二視窗等第一視窗更動完再去select),且第二視窗不會讀到交易尚未完成的資料,不過讀完資料後,無法得知該資料是否還會有人來更改。第一視窗在交易過程中,第二視窗仍可以更新(update)其他筆資料,因此同一個交易中第一視窗如有兩次以上select,每次select結果可能不盡相同。



二、隔離等級為repeatable read

1.重複以上1~6步驟再做一次, 但是第一視窗隔離等級改用repeatable read,
    ( 差別在於 repeatable read )
set transaction isolation level repeatable read

2.
我們發現在第三步驟時,第二視窗無法更新資料,被鎖定了。

打開活動監視器看處理序發現spid為55的源頭封鎖者的值為1,表示第一視窗將資料給鎖住。
再看看id為58的欄位,等候類型的值LCK_M_X ,封鎖者的值是55。



在交易中,第一視窗讀取(select)到的資料將不允許別人更改或刪除。如此保證第一視窗在交易中每次都可以讀取到相同的內容。但別人(第二視窗仍可以在該資料表insert資料,所以交易過程中如有兩次以上select時候,可能會突然多出一兩筆記錄來。這就是repeatable read的定義。


別忘了最後一步去第一視窗執行
rollback tran

三、隔離等級:Serializable



__________________________________________________________________
再度體會 Transaction 的「隔離性」
  -- SERIALIZABLE 如何預防 "phantom data"

1.第一個視窗執行以下指令:
set transaction isolation level SERIALIZABLE//記得要改isolation level
begin transaction
select * from Customers
  where CompanyName Like 'B%'
請記住where條件


2. 在第二視窗執行以下指令:
update Customers
  set CompanyName = 'Bottom-Dollar Markets 123'
  where CustomerID = 'CHOPS'
select * from Customers
  where CustomerID Like 'C%'
注意:這邊where條件跟第一視窗已經不同,
第二視窗是更新C開頭的某筆資料
並查詢C開頭的紀錄

3.發現這時第一視窗將資料給lock住了
打開活動監視器結果跟read committed一樣
看處理序發現spid為55的源頭封鎖者的值為1,表示第一視窗將資料給鎖住。

再看看id為58的欄位,等候類型的值LCK_M_X ,封鎖者的值是55。


Serializable:第一視窗會將整個資料表鎖定,不允許別人insert,delete,update資料。其他人必須排隊(serial)等第一視窗交易完畢才可以使用這個資料表。因此serializable的並行性最低。

4.記得去第一視窗執行
rollback tran





心得:實做一遍之後對於交易有概念了,光看書根本無法吸收,不夠具體無法想像。

MSSQL雜記

1.
XML資料型態,欄位存放以XML格式寫成的的文件。有點類似將一張網頁放進一個欄位。書上是以存放一張訂單來說明。
好處在於存放資料彈性、擴充性高,也帶有物件導向資料庫的意味。
一個欄位放一張訂單或放一個影音檔案。

2.
Null表示"不知道"的概念,並非零的意思也不是Null字串。

3.
新增資料表時候,日期欄位可以用getdate()函數取得系統的日期時間,
作為新增資料的日期的預設值
create table TableName(
...
FieldName datetime Default getdate(),
...
)

4.
每一個資料表、view、Index都視為物件。
M$SQL management studio左邊的物件總管的清單有.資料夾圖示的是資料庫物件。
其中:
資料圖表(diagram):以圖形表示個資料表的欄位,以及各資料表間的關聯
資料表(table):一堆資料表單,關聯資料表。
檢視(view):檢視表,也是一堆資料表,由其他資料表選取部分欄位而成。view本身是虛擬資料表。

可程式性:
預存程序(Stored Procedured):預先寫好且經過編譯的SQL程式。效率比一行一行執行SQL敘述來的好
資料庫觸發程序(trigger):存放DDL觸發程序(create table ;create database....),可以檢查資料庫所做的更改是否允許,並自訂錯誤訊息。
類型:使用者自訂資料型態。
儲存體:其中全文檢索目錄功能,用來儲存資料表欄位的全文檢索索引,讓使用者方便且有效率搜尋較長的字串欄位資料。
安全性:其中使用者、角色、結構描述,設定資料庫帳號的權限,設定某些帳號可以登入,某些帳號可以看某些資料表,或者針對資料表作更新,也可以設置黑名單。
使用者:每個資料庫都有自己一組使用者物件,表示這些帳號擁有對此DB有存取權限。dbo與guest是每個資料庫預設就會有的使用者。dbo代表該資料庫的擁有者(database owner),通常表是建立資料庫的人。guest權限預設為關閉的,當guest帳戶全線開啟後,所有使用者皆可以由guest帳戶連到資料庫。
開放guest權限好像無法由物件總管那邊用滑鼠操作,只能用指令,如下:
use databaseName
grant connect to guest
如要關閉使用者權限則:
revoke connect from guest


5.





還搞不懂的:
cursor是儲存查詢結果的資料集,其內的資料可供單筆取出處理
table可以用來暫存一組表格型式的資料
cursor跟table這兩種資料型別只能用在城市中宣告變數型別

Mysql資料複寫

複寫:當一個資料庫(master)更動資料,另一個資料庫(slave)也會跟著更動資料,達到兩邊資料同步。

步驟
1. 在 Master 伺服器建立資料複寫的專用帳號。
GRANT REPLICATION SLAVE ON *.* TO repl IDENTIFIED BY '密碼';
讓repl可以針對所有資料,進行複寫
並且設定密碼。

2. 啟用 Master 伺服器的 binary log 功能。為 Master 與 Slave 伺服器設定唯一的伺服器編號。
Master 的 my.ini 設定檔:
[mysqld]
log-bin=mysql-bin    (複寫靠這個運作)
server-id=1  (靠id 識別主機)
Slave 的 my.ini 設定檔:
[mysqld]
server-id=2

3.重新啟動 兩個MySQL 服務。
4. 記錄 Master 伺服器 binary log 的位置序號。
//FLUSH TABLES WITH READ LOCK;

//如果有做資料更新,或者master要做備份,則可以打上上面指令將資料庫lock住,如此一來master不能create  database,其他人也無法更動資料。

SHOW MASTER STATUS;
結果如下:
File             | Position |
-----------------+----------+
mysql-bin.000001 |      106 |

如果slave的資料是由master 複製貼上,則可以跳過5,6點。前面有打上readlock指令務必要Unlock tables;

5. 備份 Master 伺服器的資料庫。
C:\>mysqldump -u root -pPa$$w0rd -P 3306 --all-databases --lock-all-tables > c:\Lab\dbdump.sql
如果上面有執行read lock指令務必記得
UNLOCK TABLES;

6. 將備份檔複製到 Slave 伺服器並且回存到 Slave 伺服器。
source c:\Lab\dbdump.sql

7. 在 Slave 伺服器設定他的master,並啟用資料複寫,例如:
CHANGE MASTER TO
  MASTER_HOST='主機名稱' 或 'IP:port',
  MASTER_USER='repl',//登入master主機的帳號
  MASTER_PASSWORD='密碼',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=106;
START SLAVE;

2013年1月22日 星期二

資料庫正規化的觀念

第一正規化1NF:每個欄位只能有一個值,且要有主鍵
第二正規化2NF:選出多個主鍵能與每個欄位相依,
再依主鍵相依關係切出多張資料表。
踢掉redundant data欄位。另一說將與主鍵不相干的欄位踢掉

第三正規化3NF:將遞移關係的欄位,
再切出適當無遞移關係的資料表

第一正規化不難理解,table每個格子只能有一個值,且紀錄不可重複,所以用主鍵區別紀錄


但是第二正規化跟第三正規化
只看定義就很難理解阿.........
一直以來不懂相依的定義是什麼?何謂相依關係?
何謂遞移關係?什麼叫適當無遞移關係?
在我理解:相依就是"不獨立"的意思,遞移就是a>b且b>c則a>c
可是實在無法將資料表單與數學連接在一起......


看到BBS的database板網友Adonisy以下描述,讓我立刻明白正規化是幹嘛用的:

第二正規化為了避免屬性重複存在不同於實體,造成重複修改問題
例如顧客有地址屬性,訂單有地址屬性,如果這兩個是同個定義
你修改顧客地址就也要修改訂單

第三正規化為了避免資料刪除後,就把隱實體刪除
例如訂單中有顧客,如果顧客沒有獨立成一個實體,你刪訂單
刪著刪著,有一天顧客都會被你刪掉而找不到
所以才會有什麼遞移相依,間接相依有的沒有的名詞


正規化是一種"檢查",而非設計資料庫時以"設計正規化為主"
就是設計資料庫會先找一個方法論設計,像用 ER方法論設計
 設計完後,用正規化原理檢查是否還要再分出實體
 而非用正規化來設計資料庫
 換言之,我們 ER方法論一開始就開宗名義,實體屬性,用屬性描述實體
 在實體的眾多屬性中,找一個屬性為主鍵代表實體

SQL函數

本文章主要是MSSQL的函數
有些函數mysql裡面沒有
例如:NEWID()

SQL函數通常與select配合使用
官網部分將函數分成許多類別:
字串函數、時間函數、彙總函數


1.資料型態轉換:
convert(型態,欄位)
例如:select CONVERT(char(10),height) as total,* from student where height > 180 //int 轉成char

2.列出現在的年月日時分秒
語法:select/print GETDATE()
結果:01 23 2013 12:17AM
語法:select/print CONVERT(varchar(20),getdate())
結果:01 23 2013 12:17AM
語法:select/print CONVERT(varchar(20),getdate(),101)
結果:01/23/2013
語法:select/print CONVERT(varchar(20),getdate(),102)
結果:2013.01.23
語法:select/print CONVERT(varchar(20),getdate(),120)
結果:2013-01-23 00:17:06
3.
substring

4.
index

5.計算(符合某條件下的)紀錄筆數:count(欄位)
select count(employeeid) from table_name (where .....);
但是不會將null值算進去
如果要將null值也算進去則
select count(*) from table_name;

6.列出欄位的值域:distinct
例如:想看員工來自哪些國家
select distinct (country) from Employees;

7.隨機挑選n筆資料 :select top n ... from ... [where...] order by NEWID()
例如:從order details隨機挑選六筆資料
select top 6   * from [Order Details]  order by NEWID()
例如:樂透開獎機
select top 6 * from products where productid < 49 order by NEWID()
productid 最好是主鍵,否則會重複開獎

查詢結果會發現資料並非以任何欄位的順序排列。
那是因為NEWID()函數會產生uniqueidentifier型態的唯一資料,這種資料稱之為全域唯一識別碼(GUID),長度為十六位元組(16 bytes,32 bits)的二進位值,長相如:34D92DC7-7BEB-4825-8DF1-004B40F602C8,
因此select結果是以GUID排列。


每台電腦也有GUID值,全世界的電腦都不會產生重複的GUID

8.彙總函數
選定特定欄位,進行運算得出統計結果
max(欄位)、min(欄位)、sum(欄位)、avg(欄位)、算標準差的stdev(欄位)、算變異數的var(欄位)

2013年1月21日 星期一

MySQL基本指令

1.status:列出DB版本以及字元編碼設定
|character_set_client     | utf8
//以什麼樣的編碼接收client端的資料
| character_set_connection | utf8
| character_set_database   | utf8
//資料庫資料所用的編碼,這邊視使用的資料庫而定
| character_set_filesystem | binary
| character_set_results    | utf8
//從資料庫撈出資料以什麼編碼
| character_set_server     | utf8
//進入server端資料以什麼樣的編碼
| character_set_system     | utf8

流程:client→server→database→result

2.show variables ;
//列出DB環境變數、參數設定
show variables like 'character%';
//列出character參數設定。因為項目很多,所以可以用這語法列出想看的項目
show variables like 'data%'
//列出帶有data字串的環境變數,目前版本MySQL只會列出資料庫存放路徑,預設路徑是C:\programdata\MySQL

show create database 資料庫名稱;
//列出資料庫資料的預設編碼

set character_set_database= utf8;
set character_set_results = latin1;
//改變字元編碼,當select資料或者網頁秀出的資料為亂碼時,請愛用這個指令

SET NAMES utf8;
//同時將connect、client、server的字元編碼設定改變



ERROR 1229 (HY000): Variable 'max_connections' is a GLOBAL variable and should be set with SET GLOBAL
//有些變數是global 因此要在set之後打上global


3.use 資料庫名稱;
show databases;//列出資料庫清單
show tables;//列出table清單
select database();//看使用者目前所在的資料庫


4.建立資料表
create table changin(productid int primary key auto_increment,productname
 varchar(20),spec varchar(20),price int,remark varchar(20));

5.插入資料(注意許功蓋的問題)
use factory;
insert into changin (productname,spec,price) values('木蓋\','55*66','1');
指定table與欄位 在蓋之後加上\

6.刪除資料
delete from changin where productid <10;
delete from changin;//auto_increment繼續累加
truncate table changin;//讓auto_increment重算

7.





安裝mysql以及說明

這次安裝5.5.29版本
從oracle網站下載community server版本
需要註冊帳號跟填寫問卷(感覺很囉嗦)


安裝步驟:選擇完整安裝(complete)→一直下一步→選詳細設定組態(detailed configuration)→選developer machine(當server選server machine選項;電腦專門跑sql的話,選dedicated MySQL server machineg讓CPU資源幾乎給MySQL)→選multifunctional database採用myISAM、InnoDB這兩種資料庫引擎(myISAM效能極佳但不支援transaction,myISAM資料由儲存在硬碟上三個檔案組成
  1. .frm--儲存資料表定義,此檔案非MyISAM引擎的一部份。
  2. .MYD--存放真正的資料。
  3. .MYI--儲存索引資訊。
;InnoDB有支援ACID相容的transaction。目前只能理解到這樣...)→設定InnoDB資料存放空間,採用預設值→選擇這個資料庫會有多少人連線→
設定網路選項以及要對外連線的port,採用預設值→選擇資料庫字元編碼參數選utf8→將include bin directory in windows path打勾,這樣可以在cmd介面打mysql指令→設定密碼(看各人喜好設定允不允許匿名登入,只需要打帳號不需密碼也可登入資料庫)→execute。

完成。



(PS:如果重新安裝applying security set選項顯示打叉,那麼將program_file跟programdata底下的mysql檔案刪掉重裝一次就可以安裝成功)







USE test;
DROP TABLE Lab;
CREATE TABLE Lab
(
  id INT AUTO_INCREMENT PRIMARY KEY,
  DATA INT NOT NULL
 ) ENGINE = INNODB;
-- ) engine = MyISAM;
SHOW TABLES;
DESC lab;
INSERT INTO Lab (DATA) VALUES (100);
SELECT * FROM Lab;
START TRANSACTION;
UPDATE lab SET DATA = 200 WHERE id = 1;
 -- rollback transaction;
ROLLBACK;
SELECT * FROM Lab;

在innodb下,下rollback指令會恢復100
在myISAM則否

若不知道要用哪個引擎那麼就用InnoDB吧
ACID比較重要






sqlyog字元亂碼

原始資料:中文字表單
原本編碼是latin1
已經針對許功蓋的問題,處理過資料
將"功""蓋""許"等會與ascii code衝碼的字
在其後加上反斜線"\"

將資料庫丟在C:\programdata\...\MySQL server5.5資料夾底下
重啟mysql,匯入資料庫成功。
打上use charweb;,來到資料庫charweb底下
打上status;發現Db characterset的參數是latin1
其他的characterset參數皆為utf8
現在我們下指令
set character_set_results = latin1;
那麼select可以正常顯示中文


但是用sqlyog做如上設定之後做select也依然顯示亂碼
這是因為sqlyog的在select時候將資料以utf8呈現
因此才出現亂碼。
(我猜是應該是反斜線的問題)



當用mysql將資料dump出來時系統會預設儲存成utf8,這時用記事本打開這檔案會是亂碼。
因此我們要將dump時要儲存成latin1這時打開記事本,可以正常顯示中文,接著我們將latin1字眼設定成utf8

sqlyog備份預設也是utf8
SET character_set_results = latin1;

SET character_set_database = utf8;
//資料庫裡面資料的編碼

SET character_set_results = big5;
//mysqlserver輸出給client端的編碼




dump備份資料夾先將資料匯出來,以latin1編碼匯出,與原始資料的編碼一致性。這樣記事本打開才不會亂碼
C:\>mysqldump -u root -p123456 --default-character-set=latin1 charweb > charweb3.sql

接著打開.sql檔案,將latin1改成utf8
並且將反斜線去掉

之後source 路徑\xxx.sql 將資料庫重新匯入
finish


心得:cmd在繁體中文系統下只看得懂big5,只有cmd之下select資料庫有許功蓋的問題,因此只要將原始資料的反斜線去掉就可以在sqlyog顯示正常文字

2013年1月18日 星期五

M$SQL2008備份與還原

SQLsever完整備份時不會停止使用者交易紀錄

備份有三種類型

完整備份
會備份資料檔(.mdf)與交易記錄檔(.ldf)也就是log檔案
做差異備份或交易紀錄備份之前,一定要做一次完整備份


差異備份
只會備份資料檔.mdf,只會備份上次完整備份到現在這段時間所異動的資料
名稱典故:備份當下的資料檔與最近一次完整備份資料內容做差異比對而來

交易記錄檔備份
只會備份交易紀錄檔(.ldf)

若透過 (sql server management studio)SSMS 操作,在預設的情況下會自動截斷交易記錄
交易記錄備份的 紀錄序號 (LSN) 是從資料庫建立開始就一直連貫的

2013年1月17日 星期四

express版本無法啟動sql server agent

目前無解,去dream spark下載complete版本吧。
我原本想要用報表功能。
開啟組態管理員,裡面SQL server服務的項目顯示"遠端程序呼叫失敗",無法看到服務項目諸如SQL Server browser以及SQL Server Agent.......,那麼去windows的"服務",裡面就會有SQL server相關的服務項目。其中啟動sql server agent時候出現了"在本機電腦的SQL server Agent 服務已啟動又停止,有些服務如果並未由其他服務或程式使用,會自動停止"

查到的訊息是說express板不支援agent功能
為何不支援agent功能卻還有agent相關套件占硬碟空間呢?因為開發工程是團隊溝通的問題,發行express版本時手滑將agent一併附上去啦

MSSQL帳戶存取權限設定


設定權限有三個部分
第一部分設定使用者能否連線到DB server
可連線到DB server不代表可以存取資料庫
好比路人可以去某公司的大廳,但不能去任何一個部門
操作方法:打開sql server在伺服器(第一層)的"安全性"→登入→右健新增登入→一般→點搜尋,新增使用者帳號或某個群組。
(新增的帳號來源是由OS的控制台帳戶管理或者電腦管理裡面的帳號清單。)


第二部分設定使用者能否連到server裡面的database。
這階段設定好不代表使用者可以針對database作交易處理(select update ....等等),好比學生參觀企業可以進去企業某部門,但是不能動用部門裡的電腦。
操作方法:去某個資料庫(也就是想開放使用者連線的DB)底下的"安全性"→使用者→右健新增使用者(打上輸入名稱、設定登入名稱,其餘不用做啥)。


第三部分:設定rule,讓使用者可以針對資料庫進行交易指令,
做法:腳色→新增資料庫角色→打上角色名稱以及擁有者(我打detective,dbo)
→將conan加入→確定。
接著在detective右健→屬性→安全性實體→搜尋→下列類型所有物件→結構描述打勾→選取名稱為dbo的結構描述(我選錯結構描述,選到db_accessadmin的結構描述,難怪conan一直無法select)→權限那欄有很多項目分別表示針對資料庫各種操作,我在這裡把"選取"的"授與"打勾。如此一來conan可以針對此資料庫下select指令

用指令更改權限
語法是:grant/revoke select/update/alter/delete/drop on 物件 to user/group

以上當然可以在圖形化操作完之後叫MSSQL產生指令


ps:關於gusest目前還搞不清楚
伺服器底下"安全性"的"登入"項目沒有guest
但是各個資料庫底下安全性的登入卻有guest。
且啟動guest的權限好像只能用指令去啟動。
左上角有個下拉選單選取資料庫後
下grant connect to guest指令
卸除也是如此
revoke connect from guest

在M$官網找了一下寫道:
雖然您不能卸除 guest 使用者,但是可以在 master、tempdb 或 msdb 以外的任何資料庫中執行 REVOKE CONNECT FROM GUEST 來撤銷其 CONNECT 權限,以停用 guest 使用者。

兩台以上資料庫sever模擬環境

首先去SQL組態工具→SQL組態管理員→SQL server網路組態→MSSQL通訊協定→啟用TCP/IP(裡面有通訊埠號,其他電腦可藉由ip與埠號連接server DB,裡面有很多網卡將"已啟用"項目設定為是)。
接著SQL組態工具→SQL組態管理員→SQL server服務→重啟SQL server(MSSQL server)。
接著在SQL browser右健內容將啟動模式設定為自動,之後重啟
如此一來其他電腦想連到本資料庫不用輸入埠號也可以連到DB

(win7可以去控制台→系統管理工具→找到電腦管理,不過我win7版本不能使用群組原則管理,只採用新增使用者帳戶來練習權限了,新增一個conan的帳戶)


設定權限有三個部分
第一部分設定使用者能否連線到DB server
可連線到DB server不代表可以存取資料庫
好比路人可以去某公司的大廳,但不能去任何一個部門
操作方法:打開sql server在伺服器(第一層)的"安全性"→登入→右健新增登入→一般→點搜尋,新增使用者帳號或某個群組。
(新增的帳號來源是由OS的控制台帳戶管理或者電腦管理裡面的帳號清單。)


第二部分設定使用者能否連到server裡面的database。
這階段設定好不代表使用者可以針對database作交易處理(select update ....等等),好比學生參觀企業可以進去企業某部門,但是不能動用部門裡的電腦。
操作方法:去某個資料庫(也就是想開放使用者連線的DB)底下的"安全性"→使用者→右健新增使用者(打上輸入名稱、設定登入名稱,其餘不用做啥)。


第三部分:設定rule,讓使用者可以針對資料庫進行交易指令,
做法:腳色→新增資料庫角色→打上角色名稱以及擁有者(我打detective,dbo)
→將conan加入→確定。
接著在detective右健→屬性→安全性實體→搜尋→下列類型所有物件→結構描述打勾→選取名稱為dbo的結構描述→權限那欄有很多項目分別表示針對資料庫各種操作,我在這裡把"選取"的"授與"打勾。如此一來conan可以針對此資料庫下select指令

用指令更改權限
語法是:grant/revoke  select/update/alter/delete/drop on 物件 to user/group

以上當然可以在圖形化操作完之後叫MSSQL產生指令



2013年1月16日 星期三

列印數字金字塔?



create procedure number_triangle
@number int
AS

declare @num int =@number
declare @i int =1 --1st while index
declare @j int  --2nd while index
declare @k int  --3rd while index
declare @L int  --4rd while index
while @i<=@num
begin
 declare @result varchar(1000)= null
 set @j = 1
 set @L = @i
 set @k = 1
--印左邊數字
 while @j<=@i
 begin
  if @result is null
  set @result = (select CONVERT(varchar(20),@j))
  else
  set @result = @result+(select Convert(varchar(20), @j))

 set @j = @j +1
 end
--印中間空白字元
 if @i<10
 begin
  while @k <=(@num-@i+@num-9)*2
  begin
  set @result = @result+' '
  set @k = @k+1
  end
 end
 else
 begin
  while @k <=(@num-@i)*4
  begin
  set @result = @result+' '
  set @k = @k+1
  end
 end
--印右邊數字
 while @L >=1
 begin
  set @result = @result +(select Convert(varchar(20), @L))
  set @L = @L -1
 end

print @result
set @i = @i +1
end
GO
exec number_triangle 9
exec number_triangle 10
exec number_triangle 99

明牌出現頻率機

題目:將某段期間開出的號碼由最舊到最新的排列為原始資料
希望可以秀出開獎號碼由最近出現的排到更早出現的順序




declare @length int = (select LEN('277854130636666023097111131915'))
--計算近期開獎號碼字串長度
declare @i int = @length
declare @result varchar(10)
declare @char varchar(1)
--set @char = substring('277854130636666023097111131915',30,1)
--print @char
--select @result
while @i>0
begin
set @char = substring('277854130636666023097111131915',@i,1)
--print @char
if ((select charIndex(@char, @result)) is null )
begin
set @result = @char
--print @char
end
if ((select charIndex(@char, @result)) = 0 )
begin
set @result = @result+@char
--print @char
end
--print substring('277854130636666023097111131915',@i,1)
set @i = @i - 1
end
print @result

2013年1月15日 星期二

Select基本用法

本語法以MSSQL為主
select 基本功能:從資料表單截取使用者想要看的資料
一、基本語法
Select 想要的欄位(描述想要哪些欄位colunm資料) from 那個資料表單 where 篩選條件(描述哪些列row的資料)

例如: select * from studetnt_table where ID like "M99%"
從學生資料表單調出學號碼M99的學生資料

二、排序資料:order by
order by [欄位1,欄位2][Desc Asc]
Desc 由大到小(descend),英文字母由Z到A
Asc 由小到大(ascend),英文字母由A到Z
例如 order by Student_ID,height Desc
先以學號由大到小排序後接著再以身高由大到小排序


三、篩選條件:where子句
where 用法:
1.比較型:比較大小或比較字串。
比方抓出學號大於一百的學生資料
select studentID from student_table where StudentID>100
或者抓出住在台北的學生資料
select * from student_table where city ='Taipei'
//如果不加上單引號,會誤以為Taipei是欄位

2.樣式比較型:抓出某欄位含有XX字串的資料。
where 欄位 like '字串%'
例如:抓出姓曹的學生資料
select * from student_table where name like '曹%'
where 欄位 like '%字串%'
例如:抓出地址中住在中正路的學生資料
select * from student_table where address like'%中正路%'

例如:抓出名稱A或B開頭的顧客資料
select * from customers where customerid like '[AB]%';

例如:抓出名稱為A到D開頭的顧客資料
select * form customers where customerid like '[A-D]%'


3.區間型:指定一欄位,抓取某範圍的學生資料。
where 欄位 between 數字 and 數字2
例如:抓取身高介於165到175公分學生資料
select * from student_table where height between 165 and 175
(上述語法會抓出含身高165、175的學生資料)

4.列舉型:指定一欄位,列出多個項目,抓取欄位符合項目的學生資料
where 欄位 in (''值1,'值2','值3')
例如:抓出住在台北與台中的學生資料
select * from student_table where city in ('taipei','taichung')

抓取欄位值為null的資料
select * from student_table where tele is null
(null表示不知道的概念所以用is,用=表示指定一個value給DBsystem)



四、分組group by:
針對欄位值的種類,個別作函式運算:select 函式(欄位1) from table_name group by 欄位1[,欄位2];
例如:我想知道來自各縣市的學生有多少人
select COUNT(country) from students group by Country;


切記:select子句欄位列表必須是函數或者是group by後面的欄位

五、彙總函數篩選條件:having
我們常常會找平均大於某某數的資料,利用彙總函數avg()求算之後無法用"where function(欄位)>數值"來過濾。
彙總函數的條件篩選不能用where來達成。

因此必須用having function(欄位)>數值,過濾資料
不可寫在group by 之前
having常常跟彙總函數、group by其中之一或兩者搭配



欄位出現在group by後面,才可以出現在having 後面
select ProductName from Products group by ProductName having productname like 'A%'    ;

六、select一些眉角:



1.對於某一欄位,列出所有的值域(項目):distinct
例如我們想知道學生來自哪些城市
select distinct city from student_table
(上面語法會列出學生居住的城市,我們可以知道學生來自哪些城市)
(也可以用group by,select city from student_table group by city)


2.字串串接:字串相加之後另闢欄位名稱
select firstname,lastname,'identification number:' + convert(varchar(2),emplyeeid) as ID from employees

3.欄位之間可以運算後select成新欄位。
select (AwayScore+ HomeScore)as total,* from Game where (AwayScore+HomeScore)>10
注意的事情:指令運算期間必須參考原始屬性欄位名稱,例如以下指令:
select(AwayScore+ HomeScore)as total,* from Game where total >10
M$SQL表示....:無效的資料行名稱 'total'。

4.變數型態轉換:convert(資料型態,欄位)
以下例子將整數型態轉成money型態,select出的值有小數點
select (AwayScore/CONVERT(money,homescore)) as total,* from Game
where HomeScore > 0 and (AwayScore/HomeScore) > 10

亦或者在欄位後面*1.0也可以,但是最好不要用這個方式

5.
5.1
只列出前幾項的紀錄:top 數字
例如:列出訂購量前五大的訂單明細
先列出所有訂單明細後,以訂購量由大到小排列,最後打上top 5
select top 5  * from [Order Details] order by Quantity  desc

5.2
如果有同樣訂購量情況
那麼在top 5後面加上with ties就會列出所有第五多的訂單
稱之為回傳增列跟邊界值相同的紀錄
select top 5 with ties * from [order details] order by quantity desc

5.3
列出前n百分比的紀錄select top n percent * from table order by field
例如:列出訂購量前百分之十二的訂單明細
select  top 12 percent with ties * from [Order Details] order by Quantity;





2013年1月9日 星期三

資料庫大綱

SQL語法

select

where
order by
group by
having
join
union
subselect

update

delete

insert

虛擬表單View

索引(index)

建立資料庫

建立資料表

資料型態

建立規則、條件約束、檔案群組

設定資料圖表(設定table之間的關連)

cursor

trigger

transaction

T-SQL

安全控管

新增使用者 新增群組 設定帳號的權限
開放查詢更新刪除 alter database 與table

 

全文檢索

 

利用索引輔助鎖定

 

MySQL

安裝
設定項目
字元編碼設定
檢視資料庫結構、狀態
DDL(data definition language)
DML(data manipulator language)
資料庫引擎種類,功能,優缺點








database Index

緣起:從散亂的資料找尋想看的數據,需要將整個資料表看完才能找到想要的資料。如果將資料某些欄位排序或者分門別類後建立索引,要尋找就容易多了。

Index在db是一個schema物件。目的是使用索引路徑快速定位資料,並減少硬碟I/O次數。
index描述資料存放架構。



索引結構:SQL server以B-tree(blanced tree)結構來放索引資料,每個葉節點都是一個資料頁(data page)存放多筆資料,除了葉子節點外每個節點都是一個索引頁(index page)。每個資料頁大小為8k。
這邊資料頁好比資料表(data table)一小部分。

分成:叢集索引、非叢集索引



叢集索引?HEAP?:重建索引並編摘要表的過程
create clustered index PK_student on students(id)

非叢集索引:從原來索引建立新的索引摘要表
create nonclustered index idx-tel on students(tel)


scan 在沒有建立索引之下,動用select句子,sql server採用此方式讀取table每筆資料之後撈出資料
seek 建立索引後,server依照索引架構尋找資料


看查詢效能
下指令:set statistics io on

掃描計數 1,邏輯讀取 2,實體讀取 0,讀取前讀取 0,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。
邏輯讀取越小表示效能越好
-----------------實作include columns------------
use AdventureWorks
go

-- 建立示範專用的 DemoStore 資料表
select * into dbo.DemoStore from Sales.Store
go

-- 在沒有索引的情況下, 檢視下列指令的執行計畫
-- Hint: 資料表掃描(Table Scan)
Select CustomerID, Name
  from dbo.DemoStore
  where CustomerID = 150

查看邏輯讀取
邏輯讀取是讀取記憶體中的資料頁page次數
次數越少代表效能越好

資料表 'DemoStore'。掃描計數 1,邏輯讀取 102,實體讀取 0,讀取前讀取 0,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。

另外以下指令的效能也跟上面一樣
select * from dbo.DemoStore
(查出701筆資料)



-- 建立非叢集索引
Create nonclustered index idx_DemoStore
  on dbo.DemoStore(CustomerID)
go
-- 再次檢視下列指令的執行計畫
-- Hint: 同時使用索引搜尋"Index Seek" 與 RID查閱 "bookmark seek"


Select CustomerID, Name
  from dbo.DemoStore
  where CustomerID = 150

 -- 資料表 'DemoStore'。掃描計數 1,邏輯讀取 3,實體讀取 0,讀取前讀取 0,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。


-- 重建一次索引, 這次我們加上 include 選項
drop index idx_DemoStore on dbo.DemoStore
go
Create nonclustered index idx_DemoStore
  on dbo.DemoStore(CustomerID)
  include (Name)
go


-- 再次檢視下列指令的執行計畫
-- Hint: 這次只需索引搜尋"Index Seek"
Select CustomerID, Name
  from dbo.DemoStore
  where CustomerID = 150
go

--資料表 'DemoStore'。掃描計數 1,邏輯讀取 2,實體讀取 0,讀取前讀取 0,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。

-- 清除/還原 Lab 環境
drop table dbo.DemoStore
go


索引使用時機:
1.欄位所包含的值太廣
2.欄位包含大量空值
3.一個或多個欄位常常一起被使用於where子句或join
4.表格龐大,且大多數的select只截取不到2~4的資料列


不建議使用索引狀況:
1.欄位不常被select
2.表格常常update
3.表格較小,且大多數的select

2013年1月8日 星期二

view

view的定義:
利用實體table依照使用者需求,創造虛擬table稱之為view

例如: 資料表儲存學生的姓名、住址、電話、修課成績、興趣、生日
對老闆來說指對學生姓名住址修課成績電話有興趣,因此利用學生姓名、住址、修課成績、電話,創造虛擬表格。
j對男女朋友來說需要知道對方姓名住址電話興趣生日,因此利用這些欄位創造虛擬表格。




下面指令無法創造view
create view watchunitprice as
 (select  * from Products
order by UnitPrice )

加上top之後即可
這是M$系統設定的規則

2013年1月7日 星期一

BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT

BEGIN TRANSACTION
GO

ALTER TABLE dbo.Customers
ADD CONSTRAINT
 PK_Customers PRIMARY KEY CLUSTERED
 (
 CustomerID
 )
 WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO


ALTER TABLE dbo.Customers SET (LOCK_ESCALATION = TABLE)
GO

COMMIT

BEGIN TRANSACTION
GO
ALTER TABLE dbo.Orders ADD CONSTRAINT
 PK_Orders PRIMARY KEY CLUSTERED
 (
 OrderID
 ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

ALTER TABLE dbo.Orders ADD CONSTRAINT
 FK_Orders_Customers FOREIGN KEY
 (
 CustomerID
 ) REFERENCES dbo.Customers
 (
 CustomerID
 ) ON UPDATE  CASCADE
  ON DELETE  NO ACTION
GO



ALTER TABLE dbo.Orders SET (LOCK_ESCALATION = TABLE)
GO
COMMIT



更新規則


讓您使用下列選項更新規則:
NO ACTION、CASCADE、SET NULL、SET Default
如果您指定 NO ACTION,SQL Server Compact 就會傳回錯誤,也會回復對於父資料表中受參考資料列的更新動作。
如果您指定 CASCADE 選項,而且在父資料表中更新對應的受參考資料列,就會在參考資料表中更新此資料列。
例如,資料庫中可能有 A 和 B 兩個資料表。資料表 A 具有資料表 B 的參考關聯性:A.ItemID 外部索引鍵會參考 B.ItemID 主索引鍵。
如果在資料表 B 中的資料列執行 UPDATE 陳述式,並且針對 A.ItemID 指定 ON UPDATE CASCADE 動作,SQL Server Compact 會檢查資料表 A 中是否有一個或多個相依資料列。如果有,則資料表 A 中的相依資料列會更新,而且所參考之資料表 B 中的資料列也會更新。

刪除規則


讓您使用下列選項刪除規則:
NO ACTION、CASCADE、SET NULL、SET Default
如果您指定 NO ACTION,SQL Server Compact 就會傳回錯誤,也會回復對於父資料表中受參考資料列的刪除動作。
如果您指定 CASCADE 選項,而且在父資料表中刪除對應的受參考資料列,就會在參考資料表中刪除此資料列。
例如,資料庫中可能有 A 和 B 兩個資料表。資料表 A 具有資料表 B 的參考關聯性:A.ItemID 外部索引鍵會參考 B.ItemID 主索引鍵。
如果在資料表 B 中的資料列上執行 UPDATE 陳述式,並且針對 A.ItemID 指定 ON UPDATE CASCADE 動作,SQL Server Compact 會檢查資料表 A 中是否有一個或多個相依資料列。如果有,則資料表 A 中的相依資料列會被刪除,而所參考之資料表 B 中的資料列也會被刪除。

2013年1月6日 星期日

MS建立資料庫

CREATE DATABASE [YYPDB] ON  PRIMARY
( NAME = N'YYPDB'(這邊的N表示字串採用Unicode), FILENAME = N'c:\Program Files\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\MSSQL\DATA\YYPDB.mdf' , SIZE = 10240KB , FILEGROWTH = 1024KB )


 LOG ON
( NAME = N'YYPDB_log', FILENAME = N'c:\Program Files\Microsoft SQL Server\MSSQL10_50.SQLEXPRESS\MSSQL\DATA\YYPDB_log.ldf' , SIZE = 2048KB , FILEGROWTH = 10%)
GO
ALTER DATABASE [YYPDB] SET COMPATIBILITY_LEVEL = 100
GO
ALTER DATABASE [YYPDB] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [YYPDB] SET ANSI_NULLS OFF
GO
ALTER DATABASE [YYPDB] SET ANSI_PADDING OFF
GO
ALTER DATABASE [YYPDB] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [YYPDB] SET ARITHABORT OFF
GO
ALTER DATABASE [YYPDB] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [YYPDB] SET AUTO_CREATE_STATISTICS ON
GO
ALTER DATABASE [YYPDB] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [YYPDB] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [YYPDB] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [YYPDB] SET CURSOR_DEFAULT  GLOBAL
GO
ALTER DATABASE [YYPDB] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [YYPDB] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [YYPDB] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [YYPDB] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [YYPDB] SET  DISABLE_BROKER
GO
ALTER DATABASE [YYPDB] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [YYPDB] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [YYPDB] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [YYPDB] SET  READ_WRITE
GO
ALTER DATABASE [YYPDB] SET RECOVERY SIMPLE
GO
ALTER DATABASE [YYPDB] SET  MULTI_USER
GO
ALTER DATABASE [YYPDB] SET PAGE_VERIFY CHECKSUM 
GO
USE [YYPDB]
GO
IF NOT EXISTS (SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'PRIMARY') ALTER DATABASE [YYPDB] MODIFY FILEGROUP [PRIMARY] DEFAULT
GO