Set variable value 0 if select query returns NULL - sql

I have the code below to get the sum of a column from a table.
dim sumX as new oledbcommand
sumX.commandtext = "Select sum(Xcolumn) from [Xtable] where id = "1234""
sumX.commandtype = commandtype.text
sumX.connection = con
Dim z as oledbdatareader = sumX.executereader
If z.read then
y = z.getvalue(0)
End if
The code above works. I want to know what if the code above does not get any value (null), how can I set the value of y to zero if the query's result is null

Try changing the query to this one:
Select IIf(sum(Xcolumn) Is Null,0,sum(Xcolumn)) from [Xtable] where id = "1234"
or this one:
Select Nz(sum(Xcolumn), 0) from [Xtable] where id = "1234"
There's an IIF function in access, it's better to set to 0 in the query.
See if this helps

I just simplified your code to get more performance.It is very useful to use with aggregate functions like Count() or Sum() etc. When compare to ExecuteReader() , ExecuteScalar() uses fewer System resources
Dim sumX As New OleDbCommand
sumX.CommandText = "Select sum(Xcolumn) from [Xtable] where id = 1234"
sumX.CommandType = CommandType.Text
sumX.Connection = con
y = IIf(IsDBNull(sumX.ExecuteScalar), 0, sumX.ExecuteScalar)
ExecuteScalar() in SqlCommand Object is used for get a single value from Database after its execution. It executes SQL statements or
Stored Procedure and returned a scalar value on first column of first
row in the Result Set. If the Result Set contains more than one
columns or rows , it takes only the first column of first row, all
other values will ignore. If the Result Set is empty it will return a
Null reference.

Related

How to Safe input order by with SQLCommand in VbNet using SQLServer

Select cod,nom from tb_user where cod > #param0 order by #param1
Dim mycod = 3
Dim myorderby = "asc"
Dim _adapter = New SqlDataAdapter
cmd.CommandTimeout = timeout
cmd.Connection = _conn
cmd.CommandText = pSql
cmd.CommandType = CommandType.Text
Dim sqlParameter0 = New SqlParameter("#param0", mycod)
cmd.Parameters.Add(sqlParameter0)
Dim sqlParameter1 = New SqlParameter("#param1", myorderby)
cmd.Parameters.Add(sqlParameter1)
_adapter.SelectCommand = cmd
_adapter.Fill(_ds, "result")
I know I must replace the #param0 by the value of my variable mycod to be safe.
This is possible in the variables like the param0, but the #param1 where I put asc it gives me the following error:
the SELECT item identified by the ORDER BY number 1 contains a variable as part of the expression identitying a column position
PS: By the error it is clear the SqlParameter is not the way to input this kind of order by. Is there a way to input this kind of query safely?
You can do this by selectively ordering on the two columns.
Select cod,nom from tb_user
where cod > #param0
order by
case when #param1=1 then cod else 0 end,
case when #param1=2 then nom else 0 end
There are techniques to dynamically sort by a parameter but this can often lead to a significant slow down. I had a nightmare situation when I tried something similar.
The query worked well most of the time, but the query plan created was completely inappropriate when using a different parameter value, and the results took forever to return..
Since you're binding to a DataSet, you should just sort on the DefaultView after you call Fill().
_ds.Tables(0).DefaultView.Sort = myorderby

I want to sum column with blanks

I have a column containing amount paid in a sales table. I want to sum the column and return the result to a textbox but I am having error when the table is empty or when there are Some empty fields in the column. Please help me out. The error message I get is Object cannot be cast from DBNull to other types. My code goes thus.
Try
con.open
using command=New OledbCommand("Select SUM(Amt_Paid) From Sales Where Customer = 'Abraham';".con)
Dim total = convert.Toint32(Command.ExecutrScalar)
Textbox1.Text = total.ToString
End Using
con.Close
Reference: SQL NULL Functions
Try using one of the suggested SQL NULL function in the provided link
For Example if the connection is to SQL Server then update the query to use ISNULL which will return a default value if the field is null.
Dim sql = "SELECT SUM(ISNULL(Amt_Paid, 0)) FROM Sales WHERE Customer = 'Abraham';"
Using command = New OleDbCommand(sql, con)
Dim total = convert.Toint32(command.ExecuteScalar)
Textbox1.Text = total.ToString
End Using
In the above any time a Amt_Paid is null it will default to 0 so that no errors will be encountered when summing up the value.
If using another data store refer to the reference link provided before and see if there is an equivalent version provided.

Casting ##IDENTITY to Long (Int32) in an Access SQL query

I want to use this syntax but I cant:
Select (Clng ( ##IDENTITY ) )
Or
Clng ( select ( ##IDENTITY ) )
I want to get last inserted id in current scope and cast it to the Long type..how can I make this in one query?
..
This query worked correctly:
Select ##identity
And give me the last inserted autonumber in current session but I want to cast it to the something else in one query
In the first query , You are converting a value into long while you are retrieving it, which is a valid operation.
When you use second query , when select statement is used, you are getting a record set and not an single value.
You can not apply clng on result set but you can apply on a single value
Updated Code:
Check the sample code below:
string query = "Insert Into Categories (CategoryName) Values (?)";
string query2 = "Select ##Identity";
long ID;
string connect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|Northwind.mdb";
using (OleDbConnection conn = new OleDbConnection(connect))
{
using (OleDbCommand cmd = new OleDbCommand(query, conn))
{
cmd.Parameters.AddWithValue("", Category.Text);
conn.Open();
cmd.ExecuteNonQuery();
cmd.CommandText = query2;
ID = (long)cmd.ExecuteScalar();
}
}
I just gave the C# version of code as i was not much aware of VB or VB.Net . More over , methodology is the same

SQL variable returning 0

When I run the following SQL statement in SQL Server Management Studio it returns a count of 2
SELECT COUNT(*)
FROM Daisy_Copy2
WHERE ChargeCode = '1';
But for some reason when I run the following VB.net code the result variable returns a 0 and doesn't identify that duplicate codes exist.
Dim result As Integer
Using cmdb = New SqlCommand("SELECT COUNT(*) FROM Daisy_Copy2 WHERE ChargeCode = '1'", conn)
Int(result = cmdb.ExecuteScalar())
If result > 1 Then
MessageBox.Show("Duplicate Codes Exist!", "Billing", _
MessageBoxButtons.OK, MessageBoxIcon.Information)
Else
MsgBox(result)
End If
End Using
Can anyone help me understand why?
Any help greatly appreciated.
Instead of ExecuteNonQuery you should use ExecuteScalar
Dim result As Integer = CInt(cmd.ExecuteScalar())
ExecuteNonQuery is normally used for updates or inserts that don't leave a result, so it returns an integer telling you how many rows were affected, not the result itself.
What you most likely are meaning to use is ExecuteScalar which returns the first column of the first row in the result set returned by the query, in this case the integer containing your count.
this is just a way you can use:
Dim Sqlda = New SqlDataAdapter("SELECT COUNT(*) AS tCount FROM Daisy_Copy2 WHERE ChargeCode=1", conn)
Dim sqlds = New DataSet
Sqlda.Fill(sqlds, "Daisy_Copy2")
Dim tblRow As DataRow
For Each tblRow In sqlds.Tables("Daisy_Copy2").Rows
MsgBox(tblRow("tCount").ToString())
Next
use below link to read more about it
System.Data.SqlClient Namespace
Good luck

SQL Retrieving values from a statement with multiple selects

I have this SQL:
SELECT count (1) FROM users AS total_drafts WHERE version_replace = #sid
SELECT count (1) AS unpublished_drafts FROM users WHERE version_replace = #sid AND moderated = 0
SELECT * FROM users WHERE id = #sid ORDER By ID DESC
Which appears to be correct. However I'm having difficulty extracting the fields from the results. In vb.net I am using this code fragment:
While r.Read()
Dim o_email As String = CStr(r("email"))
Dim o_first_name As String = CStr(r("first_name"))
Dim o_last_name As String = CStr(r("last_name"))
Which is causing this error: System.IndexOutOfRangeException: email
I have checked the sql is being exucuted correctly. The sql I've posted is simply replacing a simpler statement which was feeding into the code fragment perfectly.
Why is this and how do I correct it?
the correct way:
While r.Read()
total_drafts = CInt(r("total_drafts"))
End While
r.NextResult()
While r.Read()
unpublished_drafts = CInt(r("unpublished_drafts"))
End While
error_status.Text = total_drafts & " " & unpublished_drafts
r.NextResult()
While r.Read()
Dim o_email As String = CStr(r("email"))
Dim o_first_name As String = CStr(r("first_name"))
Dim o_last_name As String = CStr(r("last_name"))
EDIT: r.NextResult() instead of r.ReadNext(), r.ReadNext() is for a DataTableReader
Assuming you are calling the whole sql statement in one go, the problem is that r.Read() will use the first datatable that is returned for the first statement(SELECT count (1) FROM users AS total_drafts WHERE version_replace = #sid ), which does not contain the email etc. fields.
You have to call r.NextResult() twice, this will move the datareader to the 3rd dataset that will contain the data from SELECT * FROM users WHERE id = #sid ORDER By ID DESC
You're returning three datasets. If "r" is a DataReader (unclear from your question) then you need to call;
r.NextResult
between your lines of code, like this;
While r.Read()
Dim o_email As String = CStr(r("email"))
r.NextResult()
Dim o_first_name As String = CStr(r("first_name"))
r.NextResult()
Dim o_last_name As String = CStr(r("last_name"))
One other possible explanation (again, unclear) is that you messed up your first column name ("email"), this would also give an out of range exception.
As far as I can understand you're trying to execute multiple statements, right?
You should separate your SQL statements with a semicolon and change the reader when you've finished with the previous one.
UPDATE:
I usually use stored procedures and return parameters for counters.
Something like this:
CREATE PROCEDURE usp_GetUsers (#sid INT, #unpublished INT OUTPUT)
AS
BEGIN
DECLARE #total_drafts INT
DECLARE #unpublished_drafts INT;
SELECT #total_drafts = count (1) FROM users WHERE version_replace = #sid
SELECT #unpublished_drafts = count (1) FROM users WHERE version_replace = #sid AND moderated = 0
SELECT * FROM users WHERE id = #sid ORDER By ID DESC
RETURN(#total_drafts)
END