Command
- 概述 在 System.Data.SqlClient 命名空間下,對應的 Command 類爲 SqlCommand,在創建 SqlCommand 實例前必須已經創建了與數據庫的連接。
SqlCommand 類中常用的構造方法如下表所示:
構造方法 | 說明 |
---|---|
SqlCommand() | 無參構造方法 |
SqlCommand(string commandText,SqlConnection conn) | 帶參的構造方法,第 1 個參數是要執行的 SQL 語句,第 2 個參數是數據庫的連接對象 |
對數據庫中對象的操作不僅包括對數據表的操作,還包括對數據庫、視圖、存儲過程等數據庫對象的操作,接下來主要介紹的是對數據表和存儲過程的操作。
在對不同數據庫對象進行操作時,SqlCommand 類提供了不同的屬性和方法,常用的屬性和方法如下表所示:
屬性或方法 | 說明 |
---|---|
CommandText | 屬性,Command 對象中要執行的 SQL 語句 |
Connection | 屬性,獲取或設置數據庫的連接對象 |
CommandType | 屬性,獲取或設置命令類型 |
Parameters | 屬性,設置 Command 對象中 SQL 語句的參數 |
ExecuteReader() | 方法,獲取執行查詢語句的結果 |
ExecuteScalar() | 方法,返回查詢結果中第 1 行第 1 列的值 |
ExecuteNonQuery() | 方法,執行對數據表的增加、刪除、修改操作,返回影響的行數 |
- 使用Command類操作數據庫 Command 類中提供了 3 種命令類型,分別是 Text、TableDirect 以及 StoredProcedure,默認情況下是 Text。
所謂 Text 類型是指使用 SQL 語句的形式,包括增加、刪除、修改以及查詢的SQL語句。
StoredProcedure 用於執行存儲過程;TableDirect 僅在 OLE DB 驅動程序中有效。
在使用 Command 類操作數據庫時需要通過以下步驟完成。
- 創建SqlCommand類的實例 創建 SqlCommand 類的實例分兩種情況,一種是命令類型爲 Text 的,一種是命令類型爲 StoredProcedure 的。
命令類型爲 Text
SqlCommand SqlCommand 類的實例名 = new SqlCommand( SQL 語句 , 數據庫連接類的實例 );
其中:
- SQL 語句:指該 SqlCommand 類的實例要執行的 SQL 語句。
- 數據庫連接類的實例:指使用 SqlConnection 類創建的實例,通常數據庫連接類的實例處於打開的狀態。
命令類型爲 StoredProcedure
SqlCommand SqlCommand 類的實例名 = new SqlCommand( 存儲過程名稱 , 數據庫連接類的實例 );
需要注意的是,存儲過程必須是當前數據庫實例中的存儲過程,並且在調用帶參數的存儲過程時,還需要在 SqlCommand 類的實例中添加對應的存儲過程參數。
爲存儲過程添加參數,需要使用 SqlCommand 類實例的 Parameters 屬性來設置,具體的代碼如下。
SqlCommand 類實例 .Parameters.Add( 參數名 , 參數值 );
- 執行對數據表的操作 在執行對數據表的操作時通常分爲兩種情況,一種是執行非查詢 SQL 語句的操作,即增加、修改、刪除的操作,一種是執行查詢 SQL 語句的操作。
執行非查詢 SQL 語句的操作
在執行非查詢 SQL 語句時並不需要返回表中的數據,直接使用 SqlCommand 類的 ExecuteNonQuery 方法即可,該方法的返回值是一個整數,用於返回 SqlCommand 類在執行 SQL 語句後,對錶中數據影響的行數。
當該方法的返回值爲 -1 時,代表 SQL 語句執行失敗,當該方法的返回值爲 0 時,代表 SQL 語句對當前數據表中的數據沒有影響。
例如 要刪除學號爲 1100 的學生的信息,而表中不存在該學號的學生的信息,SQL語句可以正常執行,但對錶中的影響行數是 0。
具體的代碼如下:
SqlCommand 類的實例 .ExecuteNonQuery();
需要注意的是,如果執行的 SQL 語句在數據庫中執行錯誤,則會產生異常,因此該部分需要進行異常處理。
執行查詢語句的操作
在執行查詢語句時通常需要返回查詢結果,SqlCommand 類中提供的 ExecuteReader 方法在執行查詢 SQL 語句後,會返回一個 SqlDataReader 類型的值,通過遍歷 SqlDataReader 類中的結果即可得到返回值。
具體的代碼如下:
SqlDataReader dr = SqlCommand 類的實例 .ExecuteReader();
此外,如果在執行查詢語句後並不需要返回所有的查詢結果,而僅需要返回一個值,例如查詢表中的記錄行數,這時可以使用 ExecuteScalar 方法。具體的代碼如下:
int returnvalue = SqlCommand 類的實例 .ExecuteScalar();
下面通過實例來演示 SqlCommand 類的使用:
- 先創建數據庫School,再創建表Student:
CREATE TABLE [dbo].[Student] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] VARCHAR (30) NOT NULL,
[Age] INT NULL,
[EnrollmentDate] DATE NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
這裏如果使用visual studio localdb時,插入中文會出現亂碼,解決方法可以參考這篇文章:
https://blog.csdn.net/xingkongtianyuzhao/article/details/103944280
- 下面是使用SqlCmd執行插入命令的示例:
這裏使用了參數化查詢SqlParameter,防止了sql注入
private void btnAddStudent_Click(object sender, EventArgs e)
{
string stuName = txtUserName.Text.Trim();
int stuAge = int.Parse(txtAge.Text.Trim());
DateTime stuEnrollMentDate = dtpEnrollmentDate.Value;
string strConn = Properties.Settings.Default.SchoolConn;
using (SqlConnection conn = new SqlConnection(strConn))
{
try
{
conn.Open();
string strSql = "insert into student(name,age,enrollmentdate) values(@name,@age,@enrollmentdate);";
SqlCommand cmd = new SqlCommand(strSql, conn);
cmd.Parameters.AddWithValue("@name", stuName);
cmd.Parameters.AddWithValue("@age", stuAge);
cmd.Parameters.AddWithValue("@enrollmentdate", stuEnrollMentDate);
int result = cmd.ExecuteNonQuery();
if (result != -1)
{
MessageBox.Show("註冊成功!");
}
else
{
MessageBox.Show("註冊失敗!");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
- 下面是使用SqlCmd執行查詢命令的示例:
private void btnSearchStudent_Click(object sender, EventArgs e)
{
string strName = txtStudentName.Text.Trim();
string strConn = Properties.Settings.Default.SchoolConn;
using (SqlConnection conn = new SqlConnection(strConn))
{
try
{
string strSql = "select * from student where name=@name";
SqlCommand cmd = new SqlCommand(strSql, conn);
cmd.Parameters.AddWithValue("@name", strName);
conn.Open();
var reader = cmd.ExecuteReader();
//兩種方式查詢
while (reader.Read())
{
MessageBox.Show("Id: " + reader.GetInt32(0).ToString());
MessageBox.Show("姓名: " + reader.GetString(1).ToString());
MessageBox.Show("年齡: " + reader.GetInt32(2).ToString());
MessageBox.Show("入學日期: " + reader.GetDateTime(3).ToString("yyyy-MM-dd"));
string result = "Id: " + reader[0] + "姓名:" + reader[1];
MessageBox.Show(result);
}
reader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
** 注意ExecuteScalar,ExecuteNoQuery,ExecuteReader的區別 **
- ExecuteNonQuery():執行命令對象的SQL語句,返回一個int類型變量,如果SQL語句是對數據庫的記錄進行操作(如記錄的增加、刪除和更新),那麼方法將返回操作所影響的記錄條數。
- ExecuteScalar():執行命令對象的SQL語句,如果SQL語句是SELECT查詢,則僅僅返回查詢結果集中的第1行第1列,而忽略其他的行 和列。該方法所返回的結果爲object類型,在使用之前必須強制轉換爲所需的類型。如果SQL語句不是SELECT查詢,則返回結果沒有任何作用。
- ExecuteReader():執行命令對象的SQL語句,在ADO.NET中,就是DataReader 對象的ExecuteReader()方法來進行數據的列出,並且我們用這個ExecuteReader()方法來顯示數據是最快的一種方法,只可以一條一條向前讀,不能返回。數據連接關閉,reader數據消失。
** 記憶:**
- ExecuteNonQuery:Query是查詢的意思,NonQuery就是不用於查詢,所以ExecuteNonQuery 除了查詢,可以執行增刪改語句;
- ExecuteScalar: Scalar是遊標意思,可以想象成釣魚的浮標,是用來釣數據的,一般用於查詢,而且釣魚一般一條一條掉,所以只返回第一行第一列的數據;
- ExecuteReader: 閱讀數據,想象成圖書,從前往後翻頁,但是它翻臉不認人,不能從後往前翻頁,而且翻臉速度特別快(查詢快);
- Command要記住防止SQL注入,最好用參數化查詢,就像釣魚的魚餌,不同的魚得用專用魚餌,投其所好,防止調上水母啥的,魚餌要放在SqlParameter裏面。
- 上一節把Command比喻爲指揮官,指揮官得知道武器庫的地址,所以初始化的時候要給他,SqlConnection;還有指揮命令,Command指揮戰鬥的兩種形式(執行命令):嘴喊(Text),簡單直接;錄音(StoredProcedure):步驟太多,嘴喊類,錄下來,按個按鈕就播放,所以任命指揮官需要兩個要素:執行命令的形式和數據庫地址。你記住了嗎???