![](/img/trans.png)
[英]What is the best way to insert Bulk Xml (XElement) data to Sql server Table using C#?
[英]What is the best way to check if a record exists in a SQL Server table using C#?
什么是最好的方法? 獲得1或0回? 或者檢查查詢中是否有行可用? 我在為ExecuteScalar辯護,但對其他答案感興趣為什么或為什么不這樣做。
//using DataReader.HasRows?
bool result = false;
var cmd = new SqlCommand("select foo, bar from baz where id = 123", _sqlConnection, _sqlTransaction);
cmd.CommandType = System.Data.CommandType.Text;
using (var r = cmd.ExecuteReader())
{
if (r != null && r.HasRows)
{
result = true;
}
}
return result;
//or using Scalar?
bool result = false;
var cmd = new SqlCommand("if exists(select foo, bar from baz where id = 123) select 1 else select 0", _sqlConnection, _sqlTransaction);
cmd.CommandType = System.Data.CommandType.Text;
int i = (int) cmd.ExecuteScalar();
result = i == 1;
return result;
存在比Count更有效,因為count需要掃描所有行以匹配條件並包含在count中,不存在。
所以ExecuteScalar存在更好。
隨着更多信息支持這個:
根據http://sqlblog.com/blogs/andrew_kelly/archive/2007/12/15/exists-vs-count-the-battle-never-ends.aspx
兩個查詢都掃描了表,但是EXISTS至少能夠對它在找到第一個匹配行后可以停止的事件進行部分掃描。 其中COUNT( )必須讀取整個表中的每一行,以確定它們是否符合條件以及有多少條件。 這是關鍵人物。 在符合WHERE子句條件的第一行之后停止工作的能力使得EXISTS如此高效。 優化器知道這種行為並且也可以將其考慮在內。 現在請記住,與現實世界中的大多數數據庫相比,這些表格相對較小。 因此,對於較大的表,COUNT( )查詢的數字將成倍增加。 您可以輕松地在具有數百萬行的表上獲得數百次或更多次讀取,但EXISTS仍然只能對可以使用索引來滿足WHERE子句的任何查詢進行一些讀取。
作為使用AdventureWorks和MSSQL 2012的簡單實驗
set showplan_all on
-- TotalSubtreeCost: 0.06216168
select count(*) from sales.Customer
-- TotalSubtreeCost: 0.003288537
select 1 where exists (select * from sales.Customer)
也可以看看
http://sqlmag.com/t-sql/exists-vs-count
更新:在ExecuteScalar vs ExecuteReader上。 在System.Data.SqlClient.SqlCommand方法的實現上看一下反匯編程序(如Reflector),顯示了一些令人驚訝的東西,它們是等價的:最終調用內部幫助程序內部SqlDataReader RunExecuteReader(CommandBehavior cmdBehavior,RunBehavior runBehavior, bool returnStream,string方法,TaskCompletionSource完成,int超時,out任務任務,bool asyncWrite = false)
返回一個SqlDataReader,ExecuteReader按原樣返回它。 而ExecuteScalar使用另一個幫助器來使用它:
private object CompleteExecuteScalar(SqlDataReader ds, bool returnSqlValue)
{
object obj2 = null;
try
{
if (!ds.Read() || (ds.FieldCount <= 0))
{
return obj2;
}
if (returnSqlValue)
{
return ds.GetSqlValue(0);
}
obj2 = ds.GetValue(0);
}
finally
{
ds.Close();
}
return obj2;
}
作為旁注,與MySQL Connector / NET(MySQL的官方ADO.NET開源驅動程序)相同,方法ExecuteScalar在內部創建DataReader(MySqlDataReader更精確)並使用它。 請參閱源文件/Src/Command.cs(來自https://dev.mysql.com/downloads/connector/net/或https://github.com/mysql/mysql-connector-net )。
簡介:關於ExecuteScalar vs ExecuteReader都會產生創建SqlDataReader的開銷,我會說差異主要是慣用的。
我會使用像if exists
的查詢來使用ExecuteScalar
。 它應該在服務器上盡可能快,並且網絡流量最小。
如果你只關心存在,我會使用標量方法,但也將TSQL更新為:
SELECT CASE WHEN EXISTS(SELECT ...) THEN 1 ELSE 0 END
我會使用ExecuteScalar
稍微不同的查詢:
string sql = "SELECT CASE WHEN exists(select NULL from baz where id = 123) THEN 1 ELSE 0 END";
var cmd = new SqlCommand(sql, _sqlConnection, _sqlTransaction);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.