[Day6] SQL server資料表建立 - SQL Server資料庫入門

在上回 [Day5] 規劃資料表,透過資料庫正規化 - SQL Server資料庫入門 中,我們經由資料庫正規化1NF->2NF->3NF將訂單表單正規化,再來我們就要使用SSMS(Microsoft SQL Server Management Studio)協助我們在資料庫中建立資料表。

在這篇中,主要涵蓋內容為:
1.如何在SQL server中建立資料表
2.如何設定自動遞增
3.欄位型別選擇

訂單示意圖:

3NF正規化後:

建立資料表orders

1.對table點右鍵>new table

2.接著會出現設計的框框

3.填入欄位與型別
在此,補充一點,金額使用decimal,不要使用float,因為以下原因:
因為float表示近似數值,存在精度損失,存有小數的值可能會造成誤差,因此使用decimal。
decimal(p,s) 需要分別指定小數的最大位數(p)和小數位的數量(s)。
p (precision) :指定小數的最大位數,小數點的左側和右側的數字的總數量不能超過p,p的取值範圍是從1到38,默認值爲18。
s (scale):指定在小數點右側的小數位數,p-s是小數點左邊的最大位數。s必須是從0到p的值,只有在指定了精度的情況下才能指定s,s的默認值是0,因此,0 <= s <= p。

延伸閱讀: [Day3] SQL Server資料型態 - SQL Server資料庫入門 可以多加參考。

4.設定主鍵(PK)

5.儲存Ctrl+S,並命名為orders

6.重新整理,左方會出現orders資料表,代表成功建立

建立資料表customers

基本上可以照前面做法建立即可。

建立資料表products

基本上可以照前面做法建立即可。

建立資料表order_details

1.建構表
這邊我把amount數量設為整數。

2.這邊注意,要把id設定為主鍵,之後設定「自動遞增」,作法是identify設定成YES

3.刷新出現order_details

資料表視圖,總覽資料表

1.建立資料表視圖

2.選取要呈現的表

3.顯示我們剛剛建立的4張表

在跟我們在先前規劃的對照

總結

如果在先前正規化好的話,那建表時真的會很輕鬆XD,就只要考慮型別即可。

欄位命名規則上,我使用「全小寫,搭配底線」的規則(參考Laravel&MySQL),如果專案有統一就用專案內的,重點是整份是一樣規則就好。ps.此外,我發現用google翻譯翻出來的英文都怪怪的,有些是形容詞、名詞等等,可能要找天弄清楚。

欄位型態上,可參考先前寫的 [Day3] SQL Server資料型態 - SQL Server資料庫入門
在這回中發現了float與decimal的差別,因此在存有小數的金額請使用decimal,避免造成誤差、不準確。

特殊規則上,如某些欄位是流水號id需要「自動遞增」,作法是identify設定成YES。

在下回,我們將開始關聯這些表。

參考資料:
https://ithelp.ithome.com.tw/articles/10214381
https://ithelp.ithome.com.tw/articles/10214308

[Day5] 規劃資料表,透過資料庫正規化 - SQL Server資料庫入門

前言

這回主要淺談一下資料庫正規化,並且規劃我們的訂單資料表。

資料庫正規化

正規化的目的:

  1. 避免資料重複或相互矛盾的情形。
  2. 使資料庫在使用時能更有效率、更容易維護。

正規化:

  1. 資料庫的正規化共可分為1NF (Normal Form)、2NF、3NF、BCNF (Boyce-Codd Normal Form)、4NF、5NF 等多個階段, 不過對於一般資料庫設計來說, 通常只需要執行到BCNF即可, 而其他更高階的正規化只有在特殊的情況下才用得到。

  2. 在資料表正規化的過程(1NF 到BCNF) 中, 每個階段都是以欄位的相依性, 做為分割資料表的依據之一。

什麼是相依性?
欄位相依:就是在資料表中,乙欄位的值必須搭配甲欄位才有意義,則我們說『乙欄位相依於甲欄位』。

第一正規化規則(1NF):

1.決定主鍵:資料表中有主鍵, 而其他所有的欄位都相依於主鍵。
2.一個欄位只能有單一值:每個欄位中都只有儲存單一值,例如: 姓名欄位中不能存放2 個人的姓名。
3.消除意義上重複的欄位:資料表中沒有意義相同的多個欄位, 例如: 姓名1、姓名2…等重複的欄位。

如果不符合一階可能會造成:存取效率低、資料長度無法確定

第二正規化規則(2NF):

1.符合1NF 的格式
2.去除『部分相依性』:各欄位與主鍵間沒有部分相依的關係。

部分相依: 只有在主鍵是由多個欄位組成時才會發生,部分相依的欄位只與主鍵中的部分欄位有相依性,而與另一部份的欄位沒有相依性。

要除去資料表中的部分相依性, 只需將部份相依的欄位分割成另外的資料表即可。
因為完成第一階時容易會有資料重複問題,因此要執行第二階。

第三正規化規則(3NF):

1.符合2NF 的格式。
2.去除『間接相依性』:各欄位與主鍵間沒有間接相依的關係。

間接(遞移)相依: 是指二個欄位並非直接相依,而是藉助其他欄位來達成資料相依的關係。例如A與B相依且B與C相依,則我們說A與C為間接相依。

消除遞移相依:非主鍵屬性的欄位都只能和候選鍵相關,非主鍵屬性的欄位彼此間應該要是獨立無關的

候選鍵:欄位組合讓資料能是唯一的,並且是最小唯一

要除去資料表中的間接相依性, 其方法和除去部分相依性完全相同。例如:可再分割成N個資料表。

Boyce-Codd 正規化(BCNF)

對於大部分資料庫來說, 通常只需要執行到第三階段的正規化即足夠了。如果資料表的主鍵是由多個欄位組成的, 則必須再執行Boyce-Codd 正規化

1.符合2NF 的格式。
2.各欄位與主鍵沒有間接相依的關係。
3.主鍵中的各欄位不可以相依於其他非主鍵的欄位。

其他

正規化的另類思考:
1.不必要的分割:正規化的工作有時候不必做的太徹底, 因為過多的資料表可能會降低系統執行的效能。
2.人工的分割:有時為了增加資料處理的效率, 我們可以將已經符合BCNF 的資料表再做分割。一個資料表擁有很多欄位, 而其中又有
很多欄位根本很少用到。那麼, 我們就可以將這些很少用到的欄位分離出來, 存放到另外一個資料表中。

正規化實作-訂單

步驟1:正規化前

步驟2:1NF後

1.決定主鍵:資料表中有主鍵, 而其他所有的欄位都相依於主鍵。
2.一個欄位只能有單一值:每個欄位中都只有儲存單一值,例如: 姓名欄位中不能存放2 個人的姓名。
3.消除意義上重複的欄位:資料表中沒有意義相同的多個欄位, 例如: 姓名1、姓名2…等重複的欄位。

把因欄位單一值的欄位獨立成另一個表、決定主鍵,因為沒有重複欄位所以不用消除。

步驟3:經過2NF & 3NF 後

2NF:
1.符合1NF 的格式
2.去除『部分相依性』:各欄位與主鍵間沒有部分相依的關係。
3NF:
1.符合2NF 的格式
2.去除『間接相依性』:各欄位與主鍵間沒有間接相依的關係。

不斷比較各個欄位與該列表的主鍵關係,把表拆出。

*出貨單號、出貨日期、運送地址、客戶簽名、總計,有部分相依性
客戶姓名、客戶電話,有部分相依性
所以各自拆成兩張表

*明細流水號、出貨單號、數量、金額、備註,有部分相依性
產品、單價,有部分相依性
所以各自拆成兩張表

出貨單表的總計容易因為出貨單明細的數量*金額而變動,因此可考慮刪掉,但有時實際上又會因廠商變動而實際上硬壓上一個金額,所以還是先留著。

我在處理時覺得2跟3很難分開做,所以做完已經3階。

然後關聯

20210905修正
為了避免未來產品單價變動,造成日後撈訂單時價格改變,因此在訂單明細增加單價

結語

第一正規化做好後,第二正規化、第三正規要注意一點去做,讓結構拆開來,日後擴充會比較容易。
我自己在2~3階時有點對定義模糊,就是不斷把不相關跟主鍵去比,然後拆出來、拉關聯。(日後如果發覺錯誤會回來改正。)
此外補充一下,我覺得這種抽象的理論比實作重要,因為他沒辦法直接複製貼上,要透過動腦去分析,是累積功力的一個好方法。

Q1:我有一點疑問在"單價"比如往後需要調用歷史資料,而商品的單價改動,會接連造成訂單對不上,所以是否該把明細流水號增加單價?
ANS:20210905補上,針對這種日後可能會調度欄位、有糾紛問題的數值,存當時寫入的值比較穩定。因為是”歷史資料”,通常會限制成不可改,只能把整筆訂單刪除。
後來看了:https://ithelp.ithome.com.tw/m/questions/10197039?fbclid=IwAR1sdXPCl2JtFvhauc76aUcEuNIEtfcvH2TzodALPmC08HL8R-7mp74eLZc
這個問題是「需求」問題,看PM或SA想怎麼呈現
簡單的答案:沒必要
複雜的答案:要看資料欄位的「變化性」

參考資料
http://140.118.9.79/UML-SASD/%E6%AD%A3%E8%A6%8F%E5%8C%96.pdf
http://9715109.blogspot.com/2010/10/12.html
https://ithelp.ithome.com.tw/articles/10229472
https://www.youtube.com/watch?v=FgQ4QrwVNk0
http://spaces.isu.edu.tw/upload/19225/0/news/postfile_349.pdf
https://www.ptt.cc/bbs/Soft_Job/M.1623612131.A.33C.html
https://ithelp.ithome.com.tw/m/questions/10197039?fbclid=IwAR1sdXPCl2JtFvhauc76aUcEuNIEtfcvH2TzodALPmC08HL8R-7mp74eLZc

[Day4] SQL Server資料庫建立 - SQL Server資料庫入門

前言

這回我們利用SQL Server建立訂單的資料庫。
並給出一個例子,模擬PM或SA給你的訂單表格,要你把它轉成資料庫型態。

訂單表單

如下:(ps.這訂單來自參考資料的內容)

建立資料庫

Database>New Database

Database>New Database
輸出資料庫名稱Orders

可以見到左方出現了Orders資料庫

結語

在這回中,我們建立了一個訂單資料庫。
在下回中,會把資料庫正規化拿出來談一下,並且設計這張訂單的資料表。

參考資料
https://ithelp.ithome.com.tw/articles/10214308
http://cc.cust.edu.tw/~ccchen/doc/db_04.pdf
https://ithelp.ithome.com.tw/articles/10229472
https://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E5%BA%93%E8%A7%84%E8%8C%83%E5%8C%96
http://140.118.9.79/UML-SASD/%E6%AD%A3%E8%A6%8F%E5%8C%96.pdf

[Day3] SQL Server資料型態 - SQL Server資料庫入門

為了能夠讓每種資料有比較好的儲存方式,所以這回來看一下SQL server內建哪些資料型態。
我們平常常見資料可能會有日期、數字、文字等等。
爬了很多文後發現SQL Server的資料型態真的爆多,所以先列舉,未來如果有用到會陸續回來修補這篇文(X)。

整數

資料型別 位元數 資料範圍
tinyint  1 Byte 0 ~ 2^8 -1
( 0 ~ 255 )
smallint  2 Bytes -2^15 ~ 2^15-1
( -32738 ~ 32767 )
int  4 Bytes

-2^31 ~ 2^31 -1
( -2147483648 ~ 2147483467)

bigint  8 Bytes -2^63~2^63 -1
(-9223372036854775808 ~ 9223372036854776807 )
bit  1 Byte  0 , 1 , Null

精確位數與浮點數

資料型別 位元數 資料範圍 備註
numeric 視精確度而定 -10^38 +1 ~ 10^38 -1
decimal 視精確度而定 -10^38 +1 ~ 10^38 -1 如果要存有小數點的錢、金額請使用decimal,不要使用float,避免造成誤差
decimal(p,s) 需要分別指定小數的最大位數(p)和小數位的數量(s)。 p (precision) :指定小數的最大位數,小數點的左側和右側的數字的總數量不能超過p,p的取值範圍是從1到38,默認值爲18。 s (scale):指定在小數點右側的小數位數,p-s是小數點左邊的最大位數。s必須是從0到p的值,只有在指定了精度的情況下才能指定s,s的默認值是0,因此,0 <= s <= p。
float  8 Bytes  -1.79E+308 ~ 1.79E+308
15 位數
不要使用float存小數點的錢,避免造成誤差。他適合儲存科學用的數字。
real  4 Bytes
-3.40E+38 ~ 3.40E+38
  7 位數

字串 - Unicode 字串 - Binary 字串

資料型別 位元數 資料範圍 備註
 char(n) 1字元 1Byte  1 ~ 8000 字元 輸入的數據長度沒有達到指定的長度時將自動以英文空格在其後面填充,讓長度達到相對應的長度。
 varchar(n) 1字元 1Byte  1 ~ 8000 字元
輸入的數據長度沒有達到指定的長度時不會在後面填充空格。
 varchar(max) 變動長度 max=2GB  1 ~ 2^31 -1 字元
輸入的數據長度沒有達到指定的長度時不會在後面填充空格。
 text 變動長度 max=2GB  1 ~ 2^31 -1 字元
 nchar(n) 1字元 2Byte  1 ~ 4000 字元 所有的文字都用2 Byte來儲存
輸入的數據長度沒有達到指定的長度時將自動以英文空格在其後面填充,讓長度達到相對應的長度。
 nvarchar(n) 1字元 2Byte  1 ~ 4000 字元 所有的文字都用2 Byte來儲存
輸入的數據長度沒有達到指定的長度時不會在後面填充空格。
 nvarchar(max) 1字元 2Byte
變動長度 max=2GB
 1 ~ 2^30 -1 字元 所有的文字都用2 Byte來儲存
輸入的數據長度沒有達到指定的長度時不會在後面填充空格。
 ntext 1字元 2Byte
變動長度 max=2GB
 1 ~ 2^30 -1 字元
 binary(n) 固定長度 8000 Bytes,不足自動補上 0x00
 1 ~ 8000 Bytes
 varbinary(n) 變動長度  1 ~ 8000 Bytes
 varbinary(max) 變動長度 max=2GB  1 ~ 2^31 -1 Bytes
 image 變動長度 max=2GB  1 ~ 2^31 -1 Bytes

日期 - 時間 - 貨幣 - Timestamp

資料型別 位元數 資料範圍
datatime  8 Bytes 1753/1/1 ~ 9999/12/31
ex: 2008-11-27 08:08:08.888
datatime2 6 bytes for precision less than 3.
7 bytes for precision 3 or 4.
All other precision require 8 bytes.2
0001-01-01 ~ 9999-12-31
smalldatatime  4 Bytes
1900/1/1 ~ 2079/6/6
ex: 2008-11-24 15:11
money  8 Bytes  -2^63 ~ 2^63 -1 小數4位
( -922337203685477.5808 ~ 922337203685477.5807)
smallmoney  4 Bytes
-2^31 ~ 2^31 -1 小數4位 
( -214748.3648 ~ 214748.3647) 
timestamp  8 Bytes 8 Bytes 的  16 進位值
uniqueidentifier  16 Bytes
16 Bytes 的 16 進位值

結語

這回以SQL Server的資料型別列舉出資料範圍,對於日後再選擇時就能稍微留意空間大小、資料的範圍等規劃問題。
自己在使用上則是字串nvarchar,整數int、科學數字用浮點數float、有小數的金額用decimal避免誤差、日期datetime2,就能解決大多問題。
而SQL Server沒有MySQL的boolean型態,要改用0、1去存,可以考慮tinyint。
而在不同時區的資料則是統一都用一個標準去儲存日期UTC時間,如果有機會未來會在寫一篇跨國時間可能會遇到的問題。

參考資料
https://docs.microsoft.com/zh-tw/sql/t-sql/data-types/data-types-transact-sql?view=sql-server-ver15
https://ithelp.ithome.com.tw/articles/10203456
https://blog.xuite.net/tolarku/blog/20968398-SQL+Data+Type+%E8%B3%87%E6%96%99%E5%9E%8B%E5%88%A5
https://docs.microsoft.com/en-us/sql/t-sql/data-types/datetime2-transact-sql?view=sql-server-ver15
https://ithelp.ithome.com.tw/articles/10213922
https://ithelp.ithome.com.tw/articles/10203456?sc=iThelpR
https://malagege.github.io/blog/2018/11/09/DB%E5%88%B0%E5%BA%95%E6%9C%89%E6%B2%92%E6%9C%89boolean%E5%9E%8B%E6%85%8B%E5%91%A2/

C# Dictionary字典操作

這次練習使用C#的字典資料結構。

Dictionary

字典型別,一個Key對上一個Value,一對一關係。
像是查字典,你查某個單字,會給你他的解釋。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Collections.Generic;

public class Program
{

public static void Main()
{
Dictionary<string, string> dictionary = new Dictionary<string, string>( ); // 建立字典key:string,value:string
dictionary.Add("LastName","Lin");
dictionary.Add("FirstName","Yu-Hsiang");

// 從字典中取出對應值
Console.WriteLine("FirstName:" + dictionary["FirstName"]);
Console.WriteLine("LastName:" + dictionary["LastName"]);

// 遍歷字典
foreach ( var item in dictionary )
{
Console.WriteLine( "Key = " + item.Key + ", Value = " + item.Value );
}
}
}

輸出

1
2
3
4
FirstName:Yu-Hsiang
LastName:Lin
Key = LastName, Value = Lin
Key = FirstName, Value = Yu-Hsiang

結語

有一對一關係的資料,可以利用字典去整理,就能不用二維陣列去做,資料也比較清楚。
如果有重複的Key值,在添加時也會跳出例外事件。例:An item with the same key has already been added.

參考資料
http://code2study.blogspot.com/2012/01/c-dictionary.html
https://ithelp.ithome.com.tw/articles/10234391
https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2?view=net-5.0

C# class宣告及使用

在C++後有很多物件導向(Object-oriented programming,OOP)的語言竄起,如JAVA、VB、C#等等。
未來可能會以C#為主要語言,所以就來練習一下C#的類別宣告吧。

物件導向程式設計

是種具有物件概念的程式設計典範,同時也是一種程式開發的抽象方針。它可能包含資料、特性、程式碼與方法。物件則指的是類別(class)的實例。物件導向程式設計可以看作一種在程式中包含各種獨立而又互相呼叫的物件的思想,這與傳統的思想剛好相反:傳統的程式設計主張將程式看作一系列函式的集合,或者直接就是一系列對電腦下達的指令。

物件導向程式語言包含Common Lisp、Python、C++、Objective-C、Smalltalk、Delphi、Java、Swift、C#、Perl、Ruby、JavaScript(雖然javascript通常都用function在寫,但ES6有class) 與 PHP等。

C# class宣告及使用

透過人(Person)的類別class,宣告一個人的實例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;

public class Program
{
public class Person{

private string name; // 內部私有的name變數

public string Name {
get{return name;} // getter 取出私有的name變數
set{this.name = value;} // setter 將value設定到私有的name變數
}

public Person(){ // 建構子
this.name = "沒有名子";
}

public Person(string name){ // 多載(Overload)的建構子,可初始化name
this.name = name;
}

}

public static void Main()
{
Person person= new Person();// 宣告一個人的實例
Console.WriteLine(person.Name);// 透過getter取出變數
person.Name = "Yu Hsiang"; // 透過setter設定變數
Console.WriteLine(person.Name); // 透過getter取出變數
}
}

輸出

1
2
沒有名子
Yu Hsiang

結語

為什麼要用getter、setter?
為了避免誤改到變數及維護性的需求。
比如,未來想要加一個*在每個人名前面,這時如果沒有setter、getter,就得改每一行的程式碼。
如果有setter、getter就像有一個緩衝的函式,可以讓我們直接在這裏面修正好值再存入。
當然,也有人不寫getter或setter,也是能運作,見仁見智,符合本身團隊需求就可以了。

C#有點簡化了getter、setter,以前在寫C++時都會寫成setName、getName,再回傳本身指標,就能無限點下去。
https://github.com/yuhsiang237/C-plusplus-homework/blob/master/HomeworkBoss/final/2/2/Place.cpp

這練習想起了大學的C++作業:
https://github.com/yuhsiang237/C-plusplus-homework

參考資料
https://zh.wikipedia.org/wiki/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1
https://docs.microsoft.com/zh-tw/dotnet/csharp/fundamentals/types/classes
https://www.w3schools.com/cs/cs_properties.php

[Day2] 主索引鍵與外部索引鍵,及其他關係鍵 - SQL Server資料庫入門

在資料庫的資料表中,我們常藉「主索引鍵(Primary Key,PK,主鍵)、外部索引鍵(Foreign Key,FK,外來鍵)」,對不同的表進行關聯,最後串起整個資料庫。

主索引鍵(Primary Key)

在一張資料表中,
唯一性且不允許重複。

外部索引鍵(Foreign Key)

在一張資料表中,
外部索引鍵並不一定要唯一。
外部索引鍵是另一個資料表的主索引鍵。

範例

以上是資料表主鍵、外來鍵的關係。

在客戶資料表中,id是主鍵。
在產品資料表中,id是主鍵。
在訂單詳情資料表中,id是主鍵;客戶id、產品id分別是外來鍵,他們各自是客戶資料表中的主鍵、產品資料表中的主鍵。

舉例:
如我想找某筆訂單中的客戶是誰,就能夠用訂單裡的客戶id去客戶資料表中找到對應的客戶。

補充

超鍵(superkey)

是指在一個資料表中,選出兩個或兩個以上的欄位組合起來,以作為唯一識別資料的欄位。

候選鍵(candidate key)

這個屬性集合始終能夠確保在關係中能唯一標識元組
在這個屬性集合中找不出真子集能夠滿足條件。

代理鍵(surrogate key)

是在當資料表中的候選鍵都不適合當主鍵時,例如資料太長,或是意義層面太多,就會請一個無意義的但唯一的欄位來代為作主鍵。

次要鍵(Secondary Key)

主要的功能是提供資料索引。資料庫系統中,除了主鍵這個唯一的識別值,可以用做索引外,也可以設定其他欄位用作資料索引,這類的鍵值並不是主鍵,但因為資料內容並不會重複,所以也可作為資料索引,這就是次要鍵。在員工資料表中,員工姓名、到職日期等欄位都沒有重複,就可以做為次要鍵,提供不同於主鍵的資料索引。

複合鍵(Composite Key)

是指資料表中的主鍵,是由兩個或兩個欄位以上所組成,這種主鍵稱為複合鍵(Composite Key)。
當表格中某一欄位的值無法區分資料記錄時可以使用此方法。

結語

在整理過各種鍵後,理解到各種鍵的使用時機。(未來可能在資料庫正規化方面能夠更加順手。)
而以自身經驗來說,實際設計過的資料表中通常只會用到主鍵、外來鍵居多,其餘的特殊鍵則比較少,甚至沒有用到的情況。

參考資料:
https://ithelp.ithome.com.tw/articles/10213896
https://rileylin91.github.io/2020/05/29/MSSQL-9-Primary-Foreign-Key/
https://zh.wikipedia.org/wiki/%E5%85%B3%E7%B3%BB%E9%94%AE
https://www.1keydata.com/tw/sql/sql-foreign-key.html
https://www.ithome.com.tw/node/46156

[Day1] SQL Server 安裝 - SQL Server資料庫入門

前言

因為工作與後端有關連,不免需要操作資料,而這些資料的儲存體就是資料庫。
網路上有不同種的SQL,如MySQL、MongoDB、SQL Server、Oracle、PostgreSQL…等等。
在未來工作上可能以關聯式資料庫(RDBMS)居多,因此以SQL Server當作練習的修練場。

在此之前需要下載:

  1. SQL Server Express:微軟的資料庫,沒有介面。
    https://www.microsoft.com/en-us/sql-server/sql-server-downloads
  2. SQL Server Management Studio:透過介面式管理SQL Server Express資料庫的工具。(約6G空間)
    https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver15

下載安裝後:

結語

這系列預計會從「資料表建立>SQL語法>進階語法」這樣前進。

目標:是練過一輪基礎SQL語法、SQL進階用法、釐清資料表設計的方式。

基本上會跟這篇 Challenge參考資料雷同,但是會加一些自己不同的見解XD。
https://ithelp.ithome.com.tw/articles/10219497

然後,也會藉由這些主題,逐漸擴充實戰經驗累積的資料。

參考資料
https://ithelp.ithome.com.tw/articles/10219497

C#亂數

前言

亂數(Random)是在程式語言中常見的內建類別。
如陣列洗牌、模擬骰子等等都會常用到,所以就來寫一下他的用法。

Random

1.Next用法
32 位元帶正負號的整數大於或等於 0,並且小於 MaxValue。

1
2
3
4
5
6
7
8
9
10
11
using System;

public class Program
{
public static void Main()
{
Random r = new Random(); //宣告亂數種子
int result = r.Next(1,7); // 可能回傳1~6的整數數字,因為Next第二個參數是小於,以此例為小於7
Console.WriteLine(result); // 可能回傳1~6的整數數字
}
}

輸出結果

1
2

2.Random洗亂陣列
以array長度洗牌,隨意骰出符合陣列的兩個index,比較是否相同,不相同就將其交換。
最後得到一個洗牌後陣列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System;

public class Program
{
public static void Main()
{
Random r = new Random(); //宣告亂數種子

int [] array = new int[5]{1,2,3,4,5}; // 宣告陣列並初始化

for(int i=0;i<array.Length;i++){
int index1 = r.Next(0,array.Length);
int index2 = r.Next(0,array.Length);
if(index1 != index2){ // 交換陣列內容
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
}
Console.WriteLine("陣列洗牌後結果:");
foreach(int item in array){
Console.WriteLine(item);
}
}
}

輸出結果

1
2
3
4
5
6
陣列洗牌後結果:
2
4
1
3
5

C# Queue與Stack操作

前言

為了熟悉C#處理資料的方式,所以找了兩種比較常見的資料結構來練習。
分別是Queue(佇列)、Stack(堆疊)。

Queue

先進先出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System;
using System.Collections;

public class Program
{
public static void Main()
{
Queue q = new Queue();
q.Enqueue("hello"); // 向 Queue 的末尾新增一個物件。
q.Enqueue(32);
q.Enqueue(5);
q.Enqueue('N');

Console.WriteLine("印出Queue的內容:");
foreach(var item in q){
Console.WriteLine(item);
}

Console.WriteLine("取出一個資料:");
var result = q.Dequeue(); // 從 Queue 的前端取出一個資料
Console.WriteLine(result);

Console.WriteLine("轉成陣列印出:");
var array = q.ToArray();
foreach(var item in array){
Console.WriteLine(item);
}
}
}

輸出:

1
2
3
4
5
6
7
8
9
10
11
印出Queue的內容:
hello
32
5
N
取出一個資料:
hello
轉成陣列印出:
32
5
N

Stack

先進後出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
using System.Collections;

public class Program
{
public static void Main()
{
Stack s = new Stack();
s.Push("hello"); // 向 Stack 的頂部新增一個物件。
s.Push(32);
s.Push(5);
s.Push('N');

Console.WriteLine("印出Stack的內容:");
foreach(var item in s){
Console.WriteLine(item);
}

Console.WriteLine("取出一個資料:");
var result = s.Pop(); // 移除並返回在 Stack 的頂部的物件。
Console.WriteLine(result);

Console.WriteLine("Peek觀察頂部物件但不移除:");
result = s.Peek(); // Peek觀察頂部物件但不移除
Console.WriteLine(result);

Console.WriteLine("轉成陣列印出:");
var array = s.ToArray();
foreach(var item in array){
Console.WriteLine(item);
}
}
}

輸出:

1
2
3
4
5
6
7
8
9
10
11
12
13
印出Stack的內容:
N
5
32
hello
取出一個資料:
N
Peek觀察頂部物件但不移除:
5
轉成陣列印出:
5
32
hello

結語

C#除了已經內置了基礎的佇列(Queue)、堆疊(Stack),還內建了一些簡易的語法。
如Contains,可以對整個資料結構去檢查是否存在某個特定元素。亦有toArray()可以快速的把資料結構轉為陣列型態。

參考資料
https://www.itread01.com/content/1550138429.html?fbclid=IwAR3ty4HR0DlmSWRMl19IFBgESeXM2aH5GsJxxcKHMGdzY6WIJm90brUzsvI