I noticed some odd behavior and hoped one of the experts could explain the difference. My UI requires an image is unique before presenting it to the user for their task. I store checksums in the database and query those for unique values. I noticed that my logic 'flips' depending on whether I use a standard SELECT query vs SELECT COUNT. I've isolated it down to this line of code but I don't understand why.
SELECT record FROM table WHERE checksum = something
//This code works correctly (true / false)
Object result = command.ExecuteScalar();
bool checksumExists = (result == null ? false : true);
//Returns TRUE no matter what
Object result = command.ExecuteScalar();
bool checksumExists = (result == DBNull.value ? false : true);
I changed to the following SQL for performance against a large table and my logic 'flipped'
SELECT COUNT (record) FROM table WHERE checksum = something
//Now this code always returns TRUE
Object result = command.ExecuteScalar();
bool checksumExists = (result == null ? false : true);
//Now this is the solution
Object result = command.ExecuteScalar();
bool checksumExists = (Convert.ToInt32(result) < 1 ? false : true);
Does the COUNT statement mean that it will always return a number, even if no rows are found?
Does the COUNT statement mean that it will always return a number, even if no rows are found?
Yes. Zero is a number. and
SELECT COUNT(someCol) c FROM table WHERE 1=2
will always return a single row, single column resultset like:
c
-----------
0
(1 row affected)
COUNT is not the most efficient way to check whether any rows meet a criterion, as it will continue to count them beyond the first.
You can use EXISTS or TOP 1 to generate a query that will stop after finding a single row. EG
select someMatchesExist = case when exists(select * from table where ...) then 1 else 0 end
or
select top (1) 1 as someMatchesExist from table where ...
Related
I have function in SQL as above, i want the value 'INTERNATIONAL' stored in the string('strIntlStudent'). How can i accomplish that? I know data reader but column has no name.
string TSQL_INTERNATIONAL = "select TOP 1 campus6.dbo.fndqgetpopulation_of_YT_v2a ('P000170620', '2017', '03TERM')";
DataTable DT_INTERNATIONAL = dhelper.ExecuteSelectCommand(TSQL_INTERNATIONAL, CommandType.Text);
if (DT_INTERNATIONAL != null && DT_INTERNATIONAL.Rows.Count > 0)
{
strIntlStudent = DT_INTERNATIONAL.Rows[0]["it says no column name"].ToString();
}
You need to give your column a name. Try this:
select TOP 1 campus6.dbo.fndqgetpopulation_of_YT_v2a
('P000170620', '2017', '03TERM') AS some_name
Then you can use that name:
strIntlStudent = DT_INTERNATIONAL.Rows[0]["some_name"].ToString();
Alternatively, if you are only retrieving one value, then you can use ExecuteScalar function which returns one value regardless of the column name and you don't need to bother with a table. Check your dhelper class to see if it has a function related to ExecuteScalar.
Suppose I have executed an update query in loop using PetaPoco like,
foreach (var obj in mainObject) {
db.Execute("update Table set Column = #0 where C1=#1 and C2 =#2", Column1, obj.data1, obj.data2);
}
How to know if each of these queries has been executed successfully ?
Execute returns the number of affected rows. So if you update one row you'd get 1 as return value if it succeded, otherwise 0 (or an error).
bool allSucceeded = true;
foreach (var obj in mainObject)
{
int updated = db.Execute("update Table set Column = #0 where C1=#1 and C2 =#2", Column1, obj.data1, obj.data2);
bool succeed = updated != 0;
if(!succeed)
allSucceeded = false;
}
So Execute doesn't return 1 for succeed and 0 for fail. It returns the number of affected rows. If you for example execute this query: DELETE FROM Table you'd delete all rows of this table and the return value would be the number of rows in this table. So it depends on the logic and the query if 0 is a fail or 1 is a succeed.
By the way, this behaviour is consistent with ADO.NET methods like SqlCommand.ExecuteNonQuery.
Usually PetaPoco returns 1 OR greater if a single query is executed successfully or means if any rows are affected and 0 if failed.
With this scenario you can trace those values by adding that in the loop, like:
List<int> checkSuccess = new List<int>(); //To trace the value returned by execute query
foreach (var obj in mainObject) {
int updated = db.Execute("update Table set Column = #0 where C1=#1 and C2 =#2", Column1, obj.data1, obj.data2);
checkSuccess.Add(updated);
}
if (checkSuccess.All(i => i >= 1))
{
//Your every queries has been updated successfully
}
foreach (var obj in mainObject)
{
var result = db.Execute("update Table set Column = #0 where C1=#1 and C2 =#2", Column1, obj.data1, obj.data2);
if (result < 1)
{
//not ok
}
}
In Sql, for example I would do:
UPDATE MyTable SET MyColum='value' WHERE Id=132
How would be the equivalent in a EF Code First database?
UPDATE:
Seeing the responses, I need to clarify my question. I am looking for an efficient way to update one column. If I use Single() or any similar function, the performance is very poor for two reasons: 1) There are 2 SQL statements, one for SELECT, and one for UPDATE, 2) The Single function retrieves all columns.
UPDATE MyTable SET MyColum='value' WHERE Id=132
The above sentence is efficient because it is only one transaction and no values are sent to the client from the server. I would like which would be the equivalent sentence in Linq Sql.
SingleOrDefault would return the object if exists in the db, or null otherwise:
var row = context.MyTable.SingleOrDefault(x => x.id == 132);
if(row != null) {
row.MyColumn = "Value";
context.SaveChanges();
}
I think it is not possible with one transaction.you need first to check that row you want to update is in your table or not
using (MyEntities me=new MyEntities())
{
if( (from t in me.MyTables where mt.Id == 132 select t).Any())
{
MyTable mt= (from t in me.MyTables where mt.Id == 132 select t).Single();
mt.MyColumn= "Value";
me.SaveChanges();
}
}
I am having a data table.
In that table there are values only in some cells.
How can I check whether a particular cell contains values or not?
Use 'IS NULL':
select *
from tableA
where row1 is null
You can also convert those empty cells to default values using ISNULL(row1, 'emptycell')
select isnull(row1, 'thiscellwasempty')
from tableA
If you need to check inside C# you can compare the cell value to System.DBNull.Value.
try this to check all cells (VB.NET):
For Each drRow As DataRow In dtTable.Rows
For i As Integer = 0 To dtTable.Columns.Count - 1
If IsDBNull(drRow(i)) Or IsNothing(drRow(i)) Or IsEmpty(drRow(i)) Then
MsgBox("DBNull, Nothing or Empty!")
End If
Next i
Next drRow
You can use LINQ
bool bIsContainData = dt.AsEnumerable().Any(s => s.Field<string>
("YourField") != null && s.Field<string>
("YourField").Trim() != ""))
I have a DataTable dt with 2 columns. First col (call it CustomerId) is unique and doesn't allow nulls. the second one allows nulls and is not unique.
From a method I get a CustomerId and then I would like to either insert a new record if this CustomerId doesn't exist or increment by 1 what's in the second column corresponding to that CustomerId if it exists.
I'm not sure how I should approach this. I wrote a select statement (which returns System.Data.DataRow) but I don't know how to test whether it returned an empty string.
Currently I have:
//I want to insert a new row
if (dt.Select("CustomerId ='" + customerId + "'") == null) //Always true :|
{
DataRow dr = dt.NewRow();
dr["CustomerId"] = customerId;
}
If the datatable is being populated by a database. I would recommend making the customerid a identity column. That way when you add a new row it will automatically create a new customerid which will be unique and 1 greater than the previous id (depending on how you setup your identity column)
I would check the row count which is returned from the select statement. Something like
I would also use string.Format...
So it would look like this
var selectStatement = string.Format("CustomerId = {0}", customerId);
var rows = dt.Select(selectStatement);
if (rows.Count < 1){
var dr = dt.NewRow();
dr["CustomerId"] = customerId;
}
This is my method to solve similar problem. You can modify it to fit your needs.
public static bool ImportRowIfNotExists(DataTable dataTable, DataRow dataRow, string keyColumnName)
{
string selectStatement = string.Format("{0} = '{1}'", keyColumnName, dataRow[keyColumnName]);
DataRow[] rows = dataTable.Select(selectStatement);
if (rows.Length == 0)
{
dataTable.ImportRow(dataRow);
return true;
}
else
{
return false;
}
}
The Select Method returns an array of DataRow objects. Just check if its length is zero (it's never null).
By the way, don't write such statements in the code directly as in this example. There's a technique for breaching your code's security called "SQL Injection", I encourage you to read the Wikipedia Article. In brief, an experienced user could write SQL script that gets executed by your database and potentially do harmful things if you're taking customerId from the user as a string. I'm not experienced in database programming, this is just "general knowledge"...