anna0212
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    1
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # C# with SQL server [SQL筆記](/Yvu8r41uQveze80lKLJvWQ)有一些相關語法、概念可供了解 (如果有需要下載SQL sever 這裡有教學可以看 https://ithelp.ithome.com.tw/m/articles/10235779 **目錄:** [TOC] ## 新增資料 ![螢幕擷取畫面 2025-02-25 103957](https://hackmd.io/_uploads/B19jTo9c1e.png) 在這即可輸入你要的行列,每行的名稱以及類型「ID,int,不允許Null」 ![螢幕擷取畫面 2025-02-25 104128](https://hackmd.io/_uploads/By91Co99kx.png) 記得要儲存以及重跑一下資料庫,就可以看到加入的資料 ![螢幕擷取畫面 2025-02-25 104551](https://hackmd.io/_uploads/H1Jb1hc5Je.png) 選取前1000、200資料列都可以手動加入資料 ![螢幕擷取畫面 2025-02-25 104743](https://hackmd.io/_uploads/rJMPy2c5ye.png) ## 建立資料庫 也可以使用新增查詢使用程式語言來新增資料庫 ```sql= CREATE DATABASE MyDatabase; ``` ### 使用資料庫 ```sql= USE MyDatabase; ``` ## 建立資料表 ```sql= CREATE TABLE Users ( UserID INT PRIMARY KEY IDENTITY(1,1), -- 自增主鍵 UserName NVARCHAR(50) NOT NULL, -- 使用 NVARCHAR 支援 Unicode Age INT CHECK (Age >= 0), -- 年齡必須大於等於 0 Email NVARCHAR(100) UNIQUE, -- Email 欄位唯一 CreatedAt DATETIME DEFAULT GETDATE() -- 預設值為當前時間 ); ``` ## 連結資料 目前看來,我常與C#進行連結,這其中大概就只有那一長串的不一樣了 以下幾種都可以連結到的 在 SSMS 內,打開 「連線屬性」 (右鍵資料庫 → 屬性 → 連線 ),可以找到伺服器名稱。 * Windows 驗證:後面為=True; * SQL Server 驗證:其中會有User Id=****;Password=****或者底部為.mdf;如此 範例: ```csharp= // 使用 Windows 驗證(Trusted Connection) string connectionString = "Server=你的伺服器名稱;Database=你的資料庫名稱;Trusted_Connection=True;"; // 使用 SQL Server 驗證(需要帳號密碼) string connectionString = "Server=你的伺服器名稱;Database=你的資料庫名稱;User Id=你的帳號;Password=你的密碼;"; ``` ### C#連結測試 ```csharp= string connectionString = "Server=localhost\SQLEXPRESS;Database=master;Trusted_Connection=True;"; using (SqlConnection conn = new SqlConnection(connectionString)) { try { conn.Open(); MessageBox.Show("✅ 成功連接到 SQL Server!"); } catch (Exception ex) { MessageBox.Show($"❌ 連線失敗:{ex.Message}"); } } ``` ## 獲取 SQL 語法 1. 開啟 SQL Server Management Studio (SSMS),並連接到你的 SQL Server。 1. 在 「物件總管」(Object Explorer) 中,找到你的 資料庫 (Database),然後展開它。 1. 在 「資料表 (Tables)」 裡找到你要查詢的表,例如 test3。 1. 右鍵點擊資料表,選擇 「Script Table as」,然後選擇你需要的 SQL 語法: * SELECT To → 產生 SELECT 查詢語法 * INSERT To → 產生 INSERT INTO 語法 * UPDATE To → 產生 UPDATE 語法 * DELETE To → 產生 DELETE 語法 5. 選擇 To New Query Editor Window,SSMS 會自動開啟一個新視窗,並顯示對應的 SQL 語法。 ![image](https://hackmd.io/_uploads/rkp0M42c1e.png) 我建議第一個用到 新增查詢編輯器視窗 ,剩下的用到 剪貼簿 ,用貼上的發法集中在一個 查詢編輯器視窗 1. CREATE : 這個指令用於創建新的資料庫物件,例如表格、索引、視圖等。 2. ALTER : 這個指令用於修改現有的資料庫物件,例如增加/刪除欄位、變更資料類型等。 1. 建立或改變為: 這個指令看起來是用於同時創建和修改資料庫物件,可能是一個複合指令。 1. DROP : 這個指令用於刪除資料庫物件,例如刪除表格、索引等。 1. DROP 並 CREATE : 這個指令看起來是先刪除再創建資料庫物件,可能是一個原子操作。 2. SELECT : 這是SQL中最常用的查詢指令,用於從數據表中選取和返回數據。它可以指定要查詢的列、過濾條件、排序方式等。 1. INSERT : 這個指令用於向數據表中插入新的記錄。可以指定要插入的列和值。 1. UPDATE : 這個指令用於更新數據表中現有的記錄。可以指定要更新的列和新的值,並添加過濾條件。 1. DELETE : 這個指令用於從數據表中刪除記錄。可以指定要刪除的記錄的過濾條件。 3. EXECUTE : 這個指令用於執行一個SQL語句或存儲過程。 ### 範例 假設你選擇 INSERT To,SSMS 可能會產生: ```sql= INSERT INTO [dbo].[test3] ([ID], [Name], [Age]) VALUES (<ID, int,>, <Name, nvarchar(50),>, <Age, int,>) ``` 你可以根據需求修改,例如: ```sql= INSERT INTO [dbo].[test3] ([ID], [Name], [Age]) VALUES (1, 'Anna', 25) ``` # C#編寫建議 ### 使用 SqlCommand 執行 SQL 建議使用 參數化查詢 ```csharp= string query = "INSERT INTO test3 (ID, Name, Age) VALUES (@id, @name, @age)"; using (SqlConnection conn = new SqlConnection("你的連線字串")) { SqlCommand cmd = new SqlCommand(query, conn); cmd.Parameters.AddWithValue("@id", 1); cmd.Parameters.AddWithValue("@name", "Anna"); cmd.Parameters.AddWithValue("@age", 25); conn.Open(); cmd.ExecuteNonQuery(); } ``` ### 注入攻擊 ❌❌ 傳統寫法 (⚠️ 不安全) 這樣的寫法 直接將變數串接進 SQL 指令,容易受到 SQL Injection (SQL 注入攻擊) 的影響 SQL Injection:是發生於應用程式與資料庫層的安全漏洞 在設計不良的程式當中忽略了字元檢查,那麼這些夾帶進去的惡意指令就會被資料庫伺服器誤認為是正常的SQL指令而執行,因此遭到破壞或是入侵。 ```csharp string query = "INSERT INTO test3 (ID, Name, Age) VALUES (" + id + ", '" + name + "', " + age + ")"; ``` ### 多行sql語法(reader開啟關閉) reader有開啟(Open)就有關閉(Close) ```csharp= //取得ID string query = @" SELECT [ID] FROM [dbo].[Account] WHERE [Username] = @Username AND [HashPassword] = @HashPassword"; using (SqlConnection conn = new SqlConnection(conn_string)) { using (SqlCommand cmd = new SqlCommand(query, conn)) { //寫入帳號密碼,這種方法有效避免sql注入風險 cmd.Parameters.AddWithValue("@Username", textBox1.Text); cmd.Parameters.AddWithValue("@HashPassword", textBox2.Text); conn.Open(); //資料庫開啟 using (SqlDataReader reader = cmd.ExecuteReader()) { if (!reader.Read()) //讀取失敗 { MessageBox.Show("帳號或密碼錯誤"); return; } //儲存帳號資訊 string id = reader["ID"].ToString(); // 關閉 reader 後執行 UPDATE reader.Close(); ////////////////////////////////////////////////////////////////////////// //更新登陸時間 string updateQuery = @" UPDATE [dbo].[Account] SET [LastUpdatedTime] = @LastUpdatedTime WHERE [ID] = @ID"; using (SqlCommand updateCmd = new SqlCommand(updateQuery, conn)) { updateCmd.Parameters.AddWithValue("@ID", id); updateCmd.Parameters.AddWithValue("@LastUpdatedTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss zzz")); updateCmd.ExecuteNonQuery(); } } } } ``` 如果要做兩個資料庫的動作,害怕**名子混在一起**,可以進行分開查詢: ```csharp= string accountId = ""; string vehicleId = ""; using (SqlConnection conn = new SqlConnection(conn_string)) { conn.Open(); // 查帳號 ID string query1 = "SELECT [ID] FROM [dbo].[Account] WHERE [Email] = @Email"; using (SqlCommand cmd1 = new SqlCommand(query1, conn)) { cmd1.Parameters.AddWithValue("@Email", email); using (SqlDataReader reader = cmd1.ExecuteReader()) { if (reader.Read()) { accountId = reader["ID"].ToString(); // 這裡的 reader["ID"] 是帳號的 ID } } } // 查車輛 ID string query2 = "SELECT [ID] FROM [dbo].[Vehicle] WHERE [AccountID] = @AccountID"; using (SqlCommand cmd2 = new SqlCommand(query2, conn)) { cmd2.Parameters.AddWithValue("@AccountID", accountId); using (SqlDataReader reader = cmd2.ExecuteReader()) { if (reader.Read()) { vehicleId = reader["ID"].ToString(); // 這裡的 reader["ID"] 是車輛的 ID } } } } ``` 如果一個sql語言中有多個表單資料: 就需要用AS特別標註 ```sql= SELECT V.ID AS VehicleID, V.PlateNumber, A.ID AS AccountID, A.Email, AWV.ID AS LinkID FROM Vehicle V --省略AS JOIN AccountWithVehicle AWV ON V.ID = AWV.VehicleID JOIN Account A ON AWV.AccountID = A.ID ``` ```csharp= using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { string vehicleId = reader["VehicleID"].ToString(); string plate = reader["PlateNumber"].ToString(); string accountId = reader["AccountID"].ToString(); string email = reader["Email"].ToString(); string linkId = reader["LinkID"].ToString(); } } ``` 總結: | 原因 | 說明 | | ---------------------------------------------- | -------------- | | 每個查詢用不同 `SqlCommand` 變數(如 `cmd1`、`cmd2`) | 避免 query 與參數混用 | | 每個讀取用不同 `SqlDataReader`(如 `reader1`、`reader2`) | 分清楚是哪張資料表的結果 | | 儲存資料用不同變數(如 `accountId`、`vehicleId`) | 確保內容不會覆蓋或混淆 | | 只開一次連線 (`conn.Open()`) | 避免重複開啟導致錯誤 | --- 💡💡記得最後的最後都要加上 ```csharp= conn.Open(); cmd.ExecuteNonQuery(); //是非同步非查詢作業(例如 INSERT/UPDATE/DELETE)。 cmd.ExecuteReader() //是同步查詢作業。 ``` 如果要查詢資料庫,請勿加 **ExecuteNonQuery()** 不能「先開始一個非同步操作」然後又「同步查詢資料」! ```csharp= using(SqlDataReader reader = comm.ExecuteReader()) //會報錯:不可因為已在進行的非同步作業擱置而先執行命令。 ``` ⚠️如果結束一段SQL語法後還要接一段,記得加上 reader.Close() SqlCommand 也是得再宣告一個使用 ```csharp= reader.Close(); // 先關閉 reader,避免與 UPDATE 衝突 string query = ...; using (SqlCommand updateCmd = new SqlCommand(updateQuery, conn)){...} ``` ---- 讀取資料後可進行的編輯方式: ```csharp= using(var reader = cmd.ExecuteReader()) { if (reader.Read()) { FirstName = reader["FirstName"].ToString(); LastName = reader["LastName"].ToString(); ..... } } ``` ### 寫空的語法 ✅ 這句: ```sql= (@EngineType IS NULL OR BM.EngineType = @EngineType ``` 意思是: 如果 `@EngineType` 是 `NULL`(代表「未指定」或「全部」),那就不要套用這個篩選條件。 否則就要符合指定的 `EngineType`。 👉 適合用於參數類型為 **數值(int) 或 可為 NULL 的欄位**。 ✅ 這句: ```sql= (@BrandCode = '' OR BM.Code = @BrandCode) ``` 意思是: 如果 @`BrandCode` 是空字串 `''`(代表「全部」),那就不要篩選品牌代號。 否則就必須等於指定的 `BrandCode`。 👉 適合用於**參數類型為 字串(string)**,例如品牌代號 Code 是 varchar。 ⚖️ 差異總結 | 比較項目 | `IS NULL` 用法 | `= ''` 用法 | | --------- | ---------------------------------------------------- | ------------------------------------------ | | 適用型別 | `int`, `datetime`, `bit` 等 | `nvarchar`, `varchar` 等字串類型 | | 預設值表示「全部」 | `null` | 空字串 `""` | | C#參數要怎麼設 | `command.Parameters.AddWithValue(..., DBNull.Value)` | `command.Parameters.AddWithValue(..., "")` | | SQL 可讀性 | 適合數值與空日期 | 適合純文字比較 | 🧠 小技巧建議你這樣記: | 條件型別 | 要排除的「全部」值 | SQL條件語法 | | ------- | ------------- | ------------------------- | | 數字或可空欄位 | `null` | `(@值 IS NULL OR 欄位 = @值)` | | 字串欄位 | `""` 或 `'全部'` | `(@值 = '' OR 欄位 = @值)` | ## SELECT 查詢資料 ```sql= SELECT 欄位1, 欄位2, ... FROM 資料表名稱 WHERE 條件; ``` ```csharp= using System; using System.Data.SqlClient; class Program { static void Main() { string connectionString = "Server=你的伺服器名稱;Database=你的資料庫名稱;Trusted_Connection=True;"; string query = "SELECT ID, Name, Age FROM test3"; using (SqlConnection conn = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand(query, conn); conn.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) //搜尋每一筆資料 { //在這裡加入條件就可以輸出所有符合條件的資料 Console.WriteLine($"ID: {reader["ID"]}, Name: {reader["Name"]}, Age: {reader["Age"]}"); } } } } } ``` 判斷資料存在 以及 存取單筆資料庫資料 ```csharp= if (reader.Read()) // 帳戶存在 { int accountStatus = Convert.ToInt32(reader["AccountStatus"]); string firstName = reader["FirstName"].ToString(); // **檢查帳戶狀態** if (accountStatus == 2) { MessageBox.Show("帳戶已被鎖定,無法登入", "警告"); return; } } ``` 🔹 ExecuteReader():用於查詢 (SELECT) 並回傳多筆資料。 ### 查詢所有資料( * ) ```sql SELECT * FROM Users; ``` ### 只查詢 UserName 和 Password ```sql SELECT UserName, Password FROM Users; ``` ### 查詢特定使用者 WHERE ```sql SELECT * FROM Users WHERE UserName = 'Anna'; ``` ### 查詢多種條件 (AND、OR) 📌 AND 與 OR 的區別 AND:兩個條件都必須滿足,才會返回結果。 OR:只要其中一個條件成立,就會返回結果。 普通時候可以加括號。AND 和 OR 混用,就需要加括號 ```sql SELECT * FROM Users WHERE UserName = 'Anna' AND Password = '12345'; ``` (在 while 底下使用判斷式來塞選,才可以列出所有相關資料) * 查詢 Id 大於 1 的使用者 ```sql SELECT * FROM Users WHERE Id > 1; ``` ### 最後一筆資料(最大 Id 的資料)ORDER BY 🔹SELECT TOP 1 *:取 最上面 1 筆資料 排序方式 | SQL 語法 | Entity Framework 語法 | 結果 ----------------------|------------------------|-------------------------------|---------------- 升序(順序排列) | ORDER BY Id ASC | OrderBy(u => u.Id) | Id 小 → 大 降序(最新資料在前) | ORDER BY Id DESC | OrderByDescending(u => u.Id) | Id 大 → 小 ```sql SELECT TOP 1 * FROM Users ORDER BY Id DESC ``` * 獲取 最後插入的 Id IDENT_CURRENT('Users') 會回傳 最後一筆 Id,不受 SESSION 限制 ```sql SELECT IDENT_CURRENT('Users') ``` ### EXISTS 資料有無存在(最佳方法) ```csharp= string query = "SELECT CASE WHEN EXISTS (SELECT 1 FROM Users WHERE UserName = @UserName) THEN 1 ELSE 0 END"; using (SqlCommand cmd = new SqlCommand(query, conn)) { cmd.Parameters.AddWithValue("@UserName", userNameToCheck); int exists = (int)cmd.ExecuteScalar(); // 執行查詢並取得結果 if (exists == 1) Console.WriteLine("資料存在"); else Console.WriteLine("資料不存在"); } ``` 📌 優點: ✅ EXISTS 會在找到符合條件的第一筆資料後就停止,不會繼續搜尋,效能較好。 ✅ 適合用於 條件判斷(例如 IF、CASE)。 ### COUNT(*) 資料有無存在 ```csharp= string query = "SELECT COUNT(*) FROM Users WHERE UserName = @UserName"; SqlCommand cmd = new SqlCommand(query, conn); cmd.Parameters.AddWithValue("@UserName", "Anna"); int count = (int)cmd.ExecuteScalar(); if (count > 0) Console.WriteLine("資料存在"); else Console.WriteLine("資料不存在"); ``` 📌 回傳值: * 0:代表資料 不存在 * 1 或以上:代表資料 存在 (也可以查看多少資料在內ouo 📌 優點: ✅ 可計算符合條件的筆數,適合用來檢查 多筆記錄 是否存在。 📌 缺點: ❌ 即使找到第一筆,仍然會繼續搜尋,可能影響效能。 ### 輸出所有符合條件的資料 除了在輸出的時候加上if條件來寫法: ```csharp= string SELECT = "SELECT [Id], [User], [Password] FROM [dbo].[Table_1];"; using (SqlConnection conn = new SqlConnection(connectionString)) { SqlCommand comm = new SqlCommand(SELECT, conn); conn.Open(); using (SqlDataReader reader = comm.ExecuteReader()) { dataGridView1.Rows.Clear(); while (reader.Read()) { if ((reader["Id"]).ToString() == textBox1.Text || (reader["User"]).ToString() == textBox2.Text || (reader["Password"]).ToString() == textBox3.Text) //是不是有更好的方法輸出所有符合條件的資料 { dataGridView1.Rows.Add(reader["Id"], reader["User"], reader["Password"]); } } } } ``` 還可以使用: 加快速度~ ```csharp= string SELECT = "SELECT [Id], [User], [Password] FROM [dbo].[Table_1] WHERE ([Id] = @id OR @id IS NULL) AND ([User] = @user OR @user IS NULL) AND ([Password] = @password OR @password IS NULL)"; using (SqlConnection conn = new SqlConnection(connectionString)) { SqlCommand comm = new SqlCommand(SELECT, conn); // 使用參數化查詢來防止SQL注入 comm.Parameters.AddWithValue("@id", string.IsNullOrEmpty(textBox1.Text) ? (object)DBNull.Value : textBox1.Text); comm.Parameters.AddWithValue("@user", string.IsNullOrEmpty(textBox2.Text) ? (object)DBNull.Value : textBox2.Text); comm.Parameters.AddWithValue("@password", string.IsNullOrEmpty(textBox3.Text) ? (object)DBNull.Value : textBox3.Text); conn.Open(); using (SqlDataReader reader = comm.ExecuteReader()) { dataGridView1.Rows.Clear(); while (reader.Read()) { dataGridView1.Rows.Add(reader["Id"], reader["User"], reader["Password"]); } } } ``` ## INSERT 新增資料 ```csharp= using System; using System.Data.SqlClient; class Program { static void Main() { string connectionString = "Server=你的伺服器名稱;Database=你的資料庫名稱;Trusted_Connection=True;"; string query = "INSERT INTO test3 (ID, Name, Age) VALUES (@id, @name, @age)"; using (SqlConnection conn = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand(query, conn); cmd.Parameters.AddWithValue("@id", 2); cmd.Parameters.AddWithValue("@name", "Bob"); cmd.Parameters.AddWithValue("@age", 30); conn.Open(); int rowsAffected = cmd.ExecuteNonQuery(); Console.WriteLine($"成功新增 {rowsAffected} 筆資料"); } } } ``` 🔹 ExecuteNonQuery():用於執行 INSERT、UPDATE、DELETE,回傳影響的資料筆數。 ### 小小總結 用途 | SQL 語法 | C# (ADO.NET) | C# (Entity Framework) ------------------|-------------------------------------------------|-------------------------------------------|------------------------------------------- 新增單筆資料 | INSERT INTO Users (User, Password) VALUES ('Anna', '123456'); | 使用 cmd.ExecuteNonQuery(); | db.Users.Add(user); db.SaveChanges(); 新增多筆資料 | INSERT INTO Users (User, Password) VALUES ('A', '1'), ('B', '2'); | 需使用迴圈插入 | 需使用迴圈插入 取得 Id | OUTPUT INSERTED.Id | (int)cmd.ExecuteScalar(); | db.Users.Add(user); db.SaveChanges(); user.Id; ## UPDATE 更新資料(修改) ```csharp= string query = "UPDATE test3 SET Name = @name WHERE ID = @id"; using (SqlConnection conn = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand(query, conn); cmd.Parameters.AddWithValue("@name", "Charlie"); cmd.Parameters.AddWithValue("@id", 2); conn.Open(); int rowsAffected = cmd.ExecuteNonQuery(); Console.WriteLine($"成功更新 {rowsAffected} 筆資料"); } ``` ### 語法說明 條件與想改變的資料可為同一欄 ( 將 Password 為 '123' 的使用者,更新為 '54321' ) ```sql= UPDATE 資料表名稱 SET 欄位1 = 值1, 欄位2 = 值2, ... WHERE 條件; ``` * 範例 有一個Anna資料在Id-1,想改變Password 成 '54321' 💡舊的資料: | Id | UserName | Password | |----|----------|----------| | 1 | Anna | 12345 | | 2 | Bob | 67890 | ```sql= UPDATE Users SET Password = '54321' WHERE Id = 1; ``` 💡新的資料: | Id | UserName | Password | |----|----------|----------| | 1 | Anna | 54321 | | 2 | Bob | 67890 | ## DELETE 刪除資料 ```csharp= string query = "DELETE FROM test3 WHERE ID = @id"; using (SqlConnection conn = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand(query, conn); cmd.Parameters.AddWithValue("@id", 2); conn.Open(); int rowsAffected = cmd.ExecuteNonQuery(); Console.WriteLine($"成功刪除 {rowsAffected} 筆資料"); } ``` ### 刪除所有資料 ```sql DELETE FROM Users ``` ### 刪除整個表 (結構+資料) ```sql DROP TABLE Users ``` ### 刪除指定的那一行 刪除與該 Id 同一行的 Name 和 Password 不影響其他相同 Name 和 Password 的行 ```sql DELETE FROM Users WHERE Id = @Id AND Name = (SELECT Name FROM Users WHERE Id = @Id) AND Password = (SELECT Password FROM Users WHERE Id = @Id); ``` ## SqlConnection 📌 SqlConnection 主要用途 * 建立與 SQL Server 資料庫的連線 * 執行 SQL 查詢(SELECT、INSERT、UPDATE、DELETE) * 管理資料庫連線的開啟 (Open()) 和關閉 (Close()) Dispose() 釋放 SqlConnection 佔用的資源 State 取得當前連線狀態("Open"、"Closed" 等) * 配合 SqlCommand 來執行 SQL 語句 * 與 SqlDataReader 或 SqlDataAdapter 搭配讀取資料 ## SqlCommand 需要注意的地方 ✅ 使用 using 確保自動釋放資源 ✅ 使用參數化查詢 (@參數) 避免 SQL Injection ✅ 確保 SqlConnection 連線字串正確,否則會無法連線 ✅ 如果 SQL Server 使用帳密登入,需要加上 User ID 和 Password 📌SqlCommand 是 C# 用來執行 SQL 指令 的物件,通常與 SqlConnection 搭配使用,能夠執行: * 查詢 (SELECT) → 取得資料 * 新增 (INSERT)、修改 (UPDATE)、刪除 (DELETE) → 操作資料 * 執行儲存程序 (Stored Procedure) * 執行資料庫指令 (ALTER TABLE, CREATE TABLE...等) ### 小小總結 * SqlCommand 用來執行 SQL 指令 * ExecuteReader():執行 SELECT,回傳 SqlDataReader * ExecuteNonQuery():執行 INSERT, UPDATE, DELETE,回傳影響的資料筆數 * ExecuteScalar():執行 COUNT(*) 或單一數值查詢 * 可搭配參數 (@參數) 避免 SQL Injection * 可執行儲存程序 (Stored Procedure) | 方法 | 作用 | |----------------------|--------------------------------------------| | ExecuteReader() | 回傳查詢結果 (SELECT),用 SqlDataReader 讀取 | | ExecuteNonQuery() | 執行 INSERT、UPDATE、DELETE,回傳影響的資料筆數 | | ExecuteScalar() | 回傳單一值(例如 COUNT(*)) | ## SqlDataReader SqlDataReader 是 C# 與 SQL Server 之間的資料讀取工具,專門用來 逐行讀取 SQL 查詢結果,適用於大量資料的高效讀取。 ### 特性 1. 只能前向讀取(Forward-Only) 📜 不能回頭,只能逐行往下讀。 2. 串流讀取(Streaming) 🚀 不會一次載入所有資料到記憶體,適合處理大量資料。 3. 唯讀(Read-Only) 🔒 不能修改資料,只能讀取。 4. 效能較快 🏎️ 因為是串流讀取,比 DataSet、DataTable 省記憶體。 ### 注意事項 * reader.Read() 回傳 true 表示還有資料可以讀取,會移動到下一行。 * 資料類型要匹配,例如 GetInt32(0) 代表該欄位應該是 int。 * 欄位索引從 0 開始(第一欄是 0,第二欄是 1,依此類推)。 ### 使用時機 ✅ 當你只需要讀取資料,而且不會修改。 ✅ 當資料量大時,避免一次載入全部到記憶體。 ✅ 當需要即時顯示資料,如讀取資料時同時寫入畫面。 ### 與DataTable 或 DataSet差別 如果需要修改、排序、篩選,請使用 DataTable 或 DataSet。 | 項目 | SqlDataReader | DataTable / DataSet | |--------------|-----------------------------|-------------------------------| | 適用場景 | 大量資料讀取(只讀) | 需要修改、過濾、排序 | | 效能 | 較快(逐行讀取) | 較慢(會載入全部資料) | | 記憶體使用 | 低(只存當前行) | 高(全部載入) | | 移動方式 | 只能往下讀 | 可隨意跳行 | # 資料匯出匯入 這個老師整理得很好!! [SQL Server資料匯入與匯出](https://www.youtube.com/watch?v=C2jEhvT0ha8&ab_channel=%E8%AC%9D%E9%82%A6%E6%98%8C) ![image](https://hackmd.io/_uploads/By3K1ZJoyx.png) # 作者書寫測試檔案 存於github,壓縮檔案類型[sql_test](https://github.com/Anna0212Anna0212/sql_test) C#檔案直接推送檔案[sql_test2.0](https://github.com/Anna0212Anna0212/sql_test2.0) 資料庫檔案都做成了Excel在檔案當中可做參考

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully