Npgsql count rows error - count

The code I have a problem with:
NpgsqlCommand if_ex = new NpgsqlCommand("SELECT count(id_unit) FROM unit WHERE name=" + "'" + tmp + "'", conn);
int ex = (int)if_ex.ExecuteScalar();
Throws an exception:
Specified cast is not valid.
I am trying to get the row count of columns that have the same name (the string that I pass)
i know I should use parameters, but at this point I am only testing a few things so I figured might as well just do it like this for now.

This problem happens because the return type of a query like: select count(*) is an long and not an int. If you change your code to long ex = (long)if_ex.ExecuteScalar(); you will get what you want. I hope it helps.

Related

can anyone tell me what's wrong in this?

public void deleteData(String name,int itemID){
SQLiteDatabase db=getWritableDatabase();
String query="DELETE FROM "+ TABLE_NAME + " WHERE "+ "'"+ COL1 +"'"+ " = "+ itemID + " AND "+ "'" + COL2 + "'" +" ="+ " '"+ name + "'";
db.execSQL(query);
db.execSQL(query);
}
The following are wrong or could be considered as wrong.
There should be no need to call the exact same query twice.
It is considered better to use the Android SDK's convenience methods when they suit (instead of using the execSQL method the delete method is more appropriate).
There is the potential for SQLinjection attacks when parameters are used directly in strings that are executed directly as SQL (note resolving 2 and using the appropriate parameters resolves this issue).
There is, unless the columns are named with invalid names, no need to enclose column names in single quotes or alternative characters (invalid names can make life difficult so if used they would be considered wrong by many).
If the delete (the first one), is not working or if the delete appears to not return an appropriate result after using pragma count_changes that could be due to the row not existing (did the row get inserted?) or that the 2nd query which would delete nothing is hiding the result of the first query.
pragma count_changes is deprecated in later version of SQLite so should no longer be used (albeit that Android's SQlite version is typically some way behind).
As a fix to all bar the id not existing you could use the following :-
public int deleteData(String name,int itemID){
SQLiteDatabase db=getWritableDatabase();
String whereclause = COL1 + "=? AND " + COL2 + "=?";
String[] whereargs = new String[]{String.valueOf(int),name};
return db.delete(TABLE_NAME,whereclause,whereargs);
}
Note that the methods signature results in an int being returned, this will be the number of rows deleted.

SqlCommand slow when executing a query with parameters

DbDataAdapter.Fill() is extremly slow when performing parameters!
I have a query with 2 parameters inside, and when I put those parameters hardcoded in the query it takes 1 second to execute (in a 470k table rows, returning only 20 rows).
I found many posts similars here and I tried all those solutions (set arithabort, option recompile, option optimize for, ...) with no luck.
I just perform a query (sql server 2008) and not a stored procedure, so the query with arithabort is like this:
string strSql = #"set ARITHABORT ON;
select TOP 20 ....
Also I tried to call set arithabort in the same transaction but performing that query first..
I don't know if I'm doing something wrong, but the sensation is the ado.net is performing a very bad execution plan in ado.net when I have defined parameters on it.
As a result of this bad choice, the execution time in SSMS is 1 second (after being cached) but in asp is like 9 seconds!
The query is something like this:
strSQL #="
select *
from Table1
where Name like #name";
And then:
DbProviderFactory factory = DbProviderFactories.GetFactory(mProvider);
DbCommand dbcmd = factory.CreateCommand();
if (CommandTimeout != null)
dbcmd.CommandTimeout = CommandTimeout.Value;
if(this.transaccion != null)
dbcmd.Transaction = this.transaccion;
dbcmd.Connection = dbc;
dbcmd.CommandText = strSQL;
if (parametros != null)
dbcmd.Parameters.AddRange(parametros);
DbDataAdapter dbda = factory.CreateDataAdapter();
dbda.SelectCommand = dbcmd;
DataTable dt = new DataTable();
dbda.Fill(dt);
return dt;
EDIT 14/01/2013 (18:44)
I'm not longer retrieve the connection from DbProviderFactory, insted I'm using directly SqlConnection and SqlCommand. I know DbCommand and DbProvider are a base clase... but I think there is something more in there.. because the performance drasticaly increase like 300%!
It's not the fill method, because I already tried in the code shown before..
Anyway, I don't know the reason why but using a SqlConnection is much faster! Any idea? Maybe isn't making that bad execution plan made before?
SqlCommand objCmd = new SqlCommand(strSQL, sqlConn);
if (CommandTimeout != null)
objCmd.CommandTimeout = CommandTimeout.Value;
if (this.transaccion != null)
objCmd.Transaction = SQLtransaccion;
if (parametros != null)
objCmd.Parameters.AddRange(parametros);
DbDataReader dbReader = objCmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dbReader);
dbReader.Close();
return dt;
Any help will be greatly appreciated,
Thanks,
I found the solution!
It was parameters!
I was using a wrong type in the the List!
Parametross.Add(bd.MakeParameter("#val", "%" + txtFind.Text + "%",
DbType.String));
DbType.String vs. DbType.AnsiString
Although both DbType.String and DbType.AnsiString deal with character data, these datatypes are processed differently, and using the wrong data type can have a negative effect on the application’s performance. DbType.String identifies the parameter as a 2-byte Unicode value and is sent to the server as such.DbType.AnsiString causes the parameter to be sent as a multibyte character string. To avoid excessive string conversions, use:
DbType.AnsiString for char or varchar columns and parameters.
DbType.String for unichar and univarchar columns and parameters.
Source:
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc20066.0115/html/adonet/adonet49.htm
In my query there is a:
....
where Table.Col1 like #val
But the column type was varchar and I should use DbType.AnsiString, instead of DbType.String
Parametross.Add(bd.MakeParameter("#val", "%" + txtFind.Text + "%",
DbType.AnsiString));
In my huge table I was making a lot of unnecesary casts and this is the reason why the performance drastically fall down!
Hope this will help someone,

ASP.NET query substring

I've got this field in my database year_start_1 and it is an integer field and an example of an ouput is 20100827 I'm trying to create a substring to create year, week, day and change the format to be 27/08/2010
Here's what i'm trying
Dim query as String = "Select * from openquery (devbook, 'SELECT cast(year_start_1 as varchar(8)) as year_start_1, DATENAME(DAY, substring(CAST(year_start_1 AS VARCHAR(8)),6,2) + DATENAME(MONTH, substring(CAST(year_start_1 AS VARCHAR(8)),4,2) + DATENAME(YEAR, substring(CAST(year_start_1 AS VARCHAR(8)),1,4))) FROM web_statements')"
It's just throwing up an error and I not sure why:
Server was unable to process request
I have tried using convert but it doesn't work.
Any ideas?
UPDATE
with Chris's suggestion
Dim query as String = "Select * from openquery (devbook, 'SELECT year_start_1, cast(year_start_1 as varchar(8)) as year_start_1, substring(CAST(year_start_1 AS VARCHAR(8)),7,2)+''/''+substring(CAST(year_start_1 AS VARCHAR(8)),5,2)+''/''+substring(CAST(year_start_1 AS VARCHAR(8)),1,4) FROM web_statements')"
Still getting the error
Thanks
UPDATE
Couldn't seem to get it to work within the query so had to do a work around in the ASP.Net code
'POINTS END DATE YEAR
Dim strPointsDateEndYear = Mid(drv.Row("year_end_1"), 3, 2)
Dim strPointsDateEndMonth = Mid(drv.Row("year_end_1"), 5,2)
Dim strPointsDateEndDay = Right(drv.Row("year_end_1"), 2)
Dim strPointsDateEnd As String = strPointsDateEndDay + "/" + strPointsDateEndMonth + "/" + strPointsDateEndYear
Thanks for the help though
Your first DATENAME doesn't seem to close all its brackets before the next DATENAME starts:
DATENAME(DAY, substring(CAST(year_start_1 AS VARCHAR(8)),6,2) + DATENAME[...]
Should I assume be:
DATENAME(DAY, substring(CAST(year_start_1 AS VARCHAR(8)),6,2)) + DATENAME[...]
Edit: Though having fixed that minor error (and converted it to debug) I'm getting errors about casting strings to dates. I'm not sure what the datename stuff is meant to do but how about this:
DECLARE #year_start_1 int
SET #year_start_1 = 20100827
SELECT cast(#year_start_1 as varchar(8)) as year_start_1,
substring(CAST(#year_start_1 AS VARCHAR(8)),7,2)+'/'+substring(CAST(#year_start_1 AS VARCHAR(8)),5,2)+'/'+substring(CAST(#year_start_1 AS VARCHAR(8)),1,4)
(converted to a non table based select for test/debug purposes)
So what you would want for your final line of sql would be (untested):
Select * from openquery (devbook, 'SELECT cast(year_start_1 as varchar(8)) as year_start_1, substring(CAST(year_start_1 AS VARCHAR(8)),7,2)+'/'+substring(CAST(year_start_1 AS VARCHAR(8)),5,2)+'/'+substring(CAST(year_start_1 AS VARCHAR(8)),1,4) FROM web_statements')
Second Edit for debug notes:
I thought it might also be worth suggesting how to debug this sort of problem. The error message suggested that the linked server you were sending the sub-statement to was unable to process the request. The first thing to try in this case would be to run the request directly on the server to see what happens. In this case in fact just parsing it on its own would have revealed the first errors I got.
Once you have your statement running form management studio or whatever directly on the server you can try converting it back into the "openquery" style statement and see if ti still works. Bascially break down your complicated scenario into lots of smaller bits to test each one individually.
select convert(varchar(10),convert(smalldatetime,'20100827'),103) will return 08/27/2010
so, your solution is:
select convert(varchar(10),convert(smalldatetime,convert(varchar,year_start_1)),103) will return 27/08/2010
You are using the datename function on strings, but it should be used on a datetime value. They are nested inside each other so you would end up with just the day, and besided it doesn't even do what you are looking for.
To get the format that you asked for, you can just use string operations to split it up in it's components and add slashes between them:
substring(CAST(year_start_1 AS VARCHAR(8)),7,2) + '/' +
substring(CAST(year_start_1 AS VARCHAR(8)),5,2) + '/' +
substring(CAST(year_start_1 AS VARCHAR(8)),1,4)

Having problems with sqlDataReader

I am using a sqlDataReader to get data and set it to session variables. The problem is it doesn't want to work with expressions. I can reference any other column in the table, but not the expressions. The SQL does work. The code is below. Thanks in advance, Anthony
Using myConnectionCheck As New SqlConnection(myConnectionString)
Dim myCommandCheck As New SqlCommand()
myCommandCheck.Connection = myConnectionCheck
myCommandCheck.CommandText = "SELECT Projects.Pro_Ver, Projects.Pro_Name, Projects.TL_Num, Projects.LP_Num, Projects.Dev_Num, Projects.Val_Num, Projects.Completed, Flow.Initiate_Date, Flow.Requirements, Flow.Req_Date, Flow.Dev_Review, Flow.Dev_Review_Date, Flow.Interface, Flow.Interface_Date, Flow.Approval, Flow.Approval_Date, Flow.Test_Plan, Flow.Test_Plan_Date, Flow.Dev_Start, Flow.Dev_Start_Date, Flow.Val_Start, Flow.Val_Start_Date, Flow.Val_Complete, Flow.Val_Complete_Date, Flow.Stage_Production, Flow.Stage_Production_Date, Flow.MKS, Flow.MKS_Date, Flow.DIET, Flow.DIET_Date, Flow.Closed, Flow.Closed_Date, Flow.Dev_End, Flow.Dev_End_Date, Users_1.Email AS Expr1, Users_2.Email AS Expr2, Users_3.Email AS Expr3, Users_4.Email AS Expr4, Users_4.FNAME, Users_3.FNAME AS Expr5, Users_2.FNAME AS Expr6, Users_1.FNAME AS Expr7 FROM Projects INNER JOIN Users AS Users_1 ON Projects.TL_Num = Users_1.PIN INNER JOIN Users AS Users_2 ON Projects.LP_Num = Users_2.PIN INNER JOIN Users AS Users_3 ON Projects.Dev_Num = Users_3.PIN INNER JOIN Users AS Users_4 ON Projects.Val_Num = Users_4.PIN INNER JOIN Flow ON Projects.id = Flow.Flow_Pro_Num WHERE id = "
myCommandCheck.CommandText += QSid
myConnectionCheck.Open()
myCommandCheck.ExecuteNonQuery()
Dim count As Int16 = myCommandCheck.ExecuteScalar
If count = 1 Then
Dim myDataReader As SqlDataReader
myDataReader = myCommandCheck.ExecuteReader()
While myDataReader.Read()
Session("TL_email") = myDataReader("Expr1").ToString()
Session("PE_email") = myDataReader("Expr2").ToString()
Session("DEV_email") = myDataReader("Expr3").ToString()
Session("VAL_email") = myDataReader("Expr4").ToString()
Session("Project_Name") = myDataReader("Pro_Name").ToString()
End While
myDataReader.Close()
End If
End Using
This may be because column names need to be unique for the SqlDataReader to be able to index them using a string name for the column.
A couple of things:
1) You are executing the query 3 times. You can lose the ExecuteNonQuery and ExecuteScalar calls, and replace the while loop with "if myDataReader.Read() / end if" to get the data values for the first resulting record. If no records are found, no session variables are set, just as in your current code.
2) It looks more like the problem lies in your session management (ie getting values from Session) rather than your sql query, which looks OK to me.
Check:
that you have sessionState enabled in your web.config file,
that you don't reset the Session values anywhere, and
that you ask for the same Session field name when you are trying to send the email. (e.g. are you setting Session("DEV_Email") but asking for Session("DEV Email") (space instead of underscore) ?
Sorry everyone. The code works just fine. The sqlDataReader WILL accept expressions as column names.
The reason I was getting an error saying the value of the from and to parameters cannot be null. There was no data in that column for any of the records in my table.

Strange result with

When i run this as my first commend i get an exception an error near "last_insert_rowid". This is referring to the last last_insert_rowid();. If i set the curser to the line command.CommandText = and run it again it is fine.
What gives? The last_insert_rowid seems to be working properly why doesnt the last_insert_rowid after the 2nd insert work.
I tried moving last_insert_rowid() to after the execute and i still get an error. What gives?
using (var trans = connection.BeginTransaction())
{
command.CommandText =
"INSERT INTO link_list(link, status, hash_type, hash_id) " +
"VALUES(#link, #status, #hash_type, #hash_id);" +
"INSERT INTO active_dl(linkId, orderNo) " +
"VALUES(last_insert_rowid(), (SELECT COUNT(*) FROM active_dl)); last_insert_rowid();";
command.Parameters.Add("#link", System.Data.DbType.String).Value = link;
command.Parameters.Add("#status", System.Data.DbType.Int32).Value = SiteBase.Status.none;
command.Parameters.Add("#hash_type", System.Data.DbType.Int32).Value = 0;
command.Parameters.Add("#hash_id", System.Data.DbType.Int32).Value = 0;
int rowid = command.ExecuteNonQuery();
trans.Commit();
}
Why is the last last_insert_rowid() there? After the second insert you call last_insert_rowid with no select or anything to identify what you want to do with it.
You would have to put a select in front of it to retrieve the value wouldn't you?
You're trying to execute 2 sql commands in the one statement. You'll need to split the 2 statements up into 2 calls and return the inserted id from the first statement.
An alternative suggestion is a stored procedure but I don't think sqlite supports these.

Resources