I have ASP.NET application and we use Dapper library. The code that produces the error looks as following:
public bool CheckIfExists(IEnumerable<long> ticketGroups, long dateId, int userId)
{
bool bRetVal = false;
string sql = "if exists (select * from T_TicketGroupsToChangePrice where SubTypeId = #SubTypeId and DateId = #dateId and UserId = #userId)";
using (var conn = CreateSqlConnection())
try
{
int rows = conn.Execute(sql, ticketGroups.Select(g => new { SubTypeId = g, UserId = userId, dateId }));
if (rows > 0)
bRetVal = true;
}
catch (SqlException ex)
{
throw new Exception("Error", ex);
}
return bRetVal;
}
When I run the application it throws the exeption: Incorrect syntax near ')'
As you can see, there can be more tickets (IEnumerable type) with the same date and user.
I'm not sure what's going on.
That is because it is not valid SQL to start with an if (If you mean to use T-SQL it is, but then you have to write the entire if statement)
I think a simple case is what you need:
select case
when exists (select * from T_TicketGroupsToChangePrice where SubTypeId = #SubTypeId and DateId = #dateId and UserId = #userId)
then 1
else 0
end
Your query "if exists (select * from T_TicketGroupsToChangePrice where SubTypeId = #SubTypeId and DateId = #dateId and UserId = #userId)" return some data if the table have some so for that it require something to work on. Like if else condition in programming we can modify this as :
if exists
(select * from T_TicketGroupsToChangePrice where SubTypeId = #SubTypeId and DateId = #dateId and UserId = #userId)
Print 'Have Data'
else
Print 'Don't Have data'
Rewriting your code :
public bool CheckIfExists(IEnumerable<long> ticketGroups, long dateId, int userId)
{
bool bRetVal = false;
string sql = "if exists (select * from T_TicketGroupsToChangePrice where SubTypeId = #SubTypeId and DateId = #dateId and UserId = #userId) Print '**your code to execute if exist data**' else Print '**your code to execute if doesnot exist data**'";
using (var conn = CreateSqlConnection())
try
{
int rows = conn.Execute(sql, ticketGroups.Select(g => new { SubTypeId = g, UserId = userId, DateId = dateId }));
if (rows > 0)
bRetVal = true;
}
catch (SqlException ex)
{
throw new Exception("Error", ex);
}
return bRetVal;
}
this link will help you more :
https://dba.stackexchange.com/questions/30159/exist-select-from-my-table
If your result depends on the number of rows and not on what's returned from the SQL, you could try this:
if exists ([whatever]) select 1
This works, because if there are no matching values, no recordset is returned, and your affected record count is zero.
You could also try something a bit simpler:
select 1
from T_TicketGroupsToChangePrice
where SubTypeId = #SubTypeId
and DateId = #dateId
and UserId = #userId;
But that has the disadvantage of returning one row for however many records you have. This could be a lot, depending on the app and the context, and in any case you don't want to pull over data that you're not going to use.
I wouldn't recommend a CASE statement, because SELECT CASE EXISTS ([whatever]) THEN 1 END will still return one record, and your affected record count will be 1 even if no records exist.
The problem with your original SQL, by the way: The statement is incomplete. You're saying "if exists ..." but you never finish it with the equivalent of a "then". You need to say "if exists() select 1" or something similar.
Related
Gridview is not populating any data from Sqlite database while saving the data in to database. Logcat is not generating any error also.
My DB is.
public Cursor getAllRows() {
SQLiteDatabase db = this.getReadableDatabase();
//String where = null;
Cursor c = db.rawQuery("SELECT * FROM " + DATAALL_TABLE, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
Mainactivity.
public void populateListView() {
Cursor cursor = db.getAllRows();
String[] fromFieldNames = new String[] {
DBHelper.COURSES_KEY_FIELD_ID1, DBHelper.FIELD_MATERIALDESC, DBHelper.FIELD_MATERIALNUM
};
int[] toViewIDs = new int[] {
R.id.textView1, R.id.textView3, R.id.textView2
};
SimpleCursorAdapter myCursorAdapter;
myCursorAdapter = new SimpleCursorAdapter(getBaseContext(), android.R.layout.activity_list_item, cursor, fromFieldNames, toViewIDs, 0);
GridView myList = (GridView) findViewById(R.id.gridView1);
myList.setAdapter(myCursorAdapter);
}
Post to the honorable member #MikeT advise its works fine but need alignment ,
as is
expected format
Your issue, assuming that there is data in the table, is likely that R.id.textView1 .... 3 are nothing to do with the layout passed to the SimpleCursorAdapter. i.e. Your issue is likely to do with the combination of the layout passed to the SimpleCursorAdapter and the Id's of the views passed as the to id's.
If you were to use :-
gridview = this.findViewById(R.id.gridView1);
csr = DBHelper.getAllRows();
myCursorAdapter = new SimpleCursorAdapter(
getBaseContext(),
//android.R.layout.simple_list_item_2,
android.R.layout.activity_list_item,
csr,
new String[]{
SO50674769DBHelper.COURSES_KEY_FIELD_ID1
//SO50674769DBHelper.FIELD_MATERIALDESC,
//SO50674769DBHelper.FIELD_MATERIALNUM
},
new int[]{android.R.id.text1}, //<<<< ID of the available view
0
);
gridview.setAdapter(myCursorAdapter);
Then result would be along the lines of :-
Changing to use a different stock layout and 2 fields as per :-
gridview = this.findViewById(R.id.gridView1);
csr = DBHelper.getAllRows();
myCursorAdapter = new SimpleCursorAdapter(
getBaseContext(),
android.R.layout.simple_list_item_2,
//android.R.layout.activity_list_item, //<<<< Changed Layout
csr,
new String[]{
SO50674769DBHelper.COURSES_KEY_FIELD_ID1,
SO50674769DBHelper.FIELD_MATERIALDESC,
//SO50674769DBHelper.FIELD_MATERIALNUM
},
new int[]{android.R.id.text1, android.R.id.text2}, //<<<< ID's of the 2 views
0
);
gridview.setAdapter(myCursorAdapter);
Note The DatabaseHelper class is so named for my convenience.
Would result in :-
As such I suspect that you need to change the layout to a one of your own.
Additionally, as hinted at your getAllRows method is not at all ideal.
Checking for a null Cursor is useless as a Cursor returned from rawQuery will not be null. It may be empty in which case the Cursor getCount method would return 0 ().
moveToFirst is also a waste.
Simply have :-
public Cursor getAllRows() {
SQLiteDatabase db = this.getReadableDatabase();
return db.rawQuery("SELECT * FROM " + DATAALL_TABLE, null);
}
I am trying to check if a table is empty. I code this method:
public boolean checkIfNULL()
throws SQLException, ClassNotFoundException {
boolean flag=false;
System.out.println("Checking if table is empty...");
String sq = "select count(*) from TABLE1";
try {
Class.forName(typeDB);
c = DriverManager.getConnection(path);
stm = c.prepareStatement(sq);
PreparedStatement stm = c.prepareStatement(sq);
int rowsAffected = stm.executeUpdate();
if(rowsAffected == 0)
flag=true;
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (stm != null) {
stm.close();
}
if (c != null) {
c.close();
}
}
return flag;
}
but sth wrong is hapenning and I get an error message
Query returns results
Exceptionn: java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (Connection is closed)
How I check the returning value of check?
UPDATE 1:
Instead of the query above, I tried also SELECT EXISTS(SELECT 1 FROM TABLE1)
but the same is happening..
UPDATE 2:
I used this:
ResultSet rs = stm.executeQuery();
if(!rs.next())
flag=true;
else
System.err.println("ERROR - The table has records...");
and it prints the ERROR - "The table has records...". How is this possible? I see the table through SQLite manager and it is empty!
You are executing a SELECT, so you need to use executeQuery, not executeUpdate. executeUpdate is for statements like UPDATE, DELETE and INSERT, executeQuery is for executing statements that return a result set (like SELECT).
You need to execute a select statement, and do:
try (ResultSet rs = stm.executeQuery()) {
rs.next(); // You always have a row, with the count
int count = rs.getInt(1);
flag = count == 0;
}
The code in your update won't work, because if you do a SELECT count(*) FROM table, then you always have one row (with the count).
I have a scan finding and hope someone can provide any ideas as to best ways to resolve the issue. First I will show the scan Finding then my code and finally what the scanner's recommended solution is.
Finding
Without proper access control, the method GetAttributeKey() in Provider.cs can execute a SQL statement on line 163 that contains an attacker-controlled primary key, thereby allowing the attacker to access unauthorized records.
Rather than relying on the presentation layer to restrict values submitted by the user, access control should be handled by the application and database layers. Under no circumstances should a user be allowed to retrieve or modify a row in the database without the appropriate permissions. Every query that accesses the database should enforce this policy, which can often be accomplished by simply including the current authenticated username as part of the query.
My Code:
Offending line:
myParam.SqlParam.Value = attribute;
Method:
public string GetAttributeKey(string attribute)
{
string qry = "SELECT ws_attribute_key FROM webservice_attributes WHERE ws_attribute = #attribute";
QueryContainer Instance = new QueryContainer(qry);
MyParam myParam = new MyParam();
myParam.SqlParam = new SqlParameter("#attribute", Instance.AddParameterType(_DbTypes._string));
myParam.SqlParam.Value = attribute;
Instance.parameterList.Add(myParam);
object key = ExecuteScaler(Instance);
return Convert.ToString(key);
}
Scanner's Recommend fix:
string user = ctx.getAuthenticatedUserName();
int16 id = System.Convert.ToInt16(invoiceID.Text);
SqlCommand query = new SqlCommand(
"SELECT * FROM invoices WHERE id = #id AND user = #user", conn);
query.Parameters.AddWithValue("#id", id);
query.Parameters.AddWithValue("#user", user);
SqlDataReader objReader = query.ExecuteReader();
I think the problem is dealing with the code calling the GetAttributeKey. The method is called only if the user has no access to to the Attribute. I think I need some type of checking. Here is the calling code:
if (result.Rows.Count > 0)
{
// get the attribute
DataRow[] rows = result.Select("ws_attribute = '" + attribute + "'");
if (rows.Length > 0)
{
// check time range
string hr = DateTime.Now.Hour.ToString();
DataRow[] valid = result.Select("ws_attribute = '" + attribute + "' AND start_time <= " + hr + " AND end_time >= " + hr);
if (valid.Length > 0)
{
ws_user_attribute_key = Convert.ToInt32(valid[0]["ws_user_attribute_key"].ToString());
ret = true;
// generate salt
TextEncryptor te = new TextEncryptor();
salt = te.CreateSalt(8);
// save to the log, return false if failed to log
if (!LogTransfer(ipAddress, accessDate, fileName, ws_user_attribute_key, salt, out logKey))
return false;
}
else
{
ret = false;
LogInvalidAccess(username, rows[0]["ws_attribute_key"].ToString(), ipAddress, accessDate, WSInvalidAccessReason.OutsideValidTimeRange);
}
}
else
{
// if user has no access to attribute
ret = false;
LogInvalidAccess(username, GetAttributeKey(attribute), ipAddress, accessDate, WSInvalidAccessReason.AttributeNotAccessible);
}
}
else
{
ret = false;
LogInvalidAccess(username, GetAttributeKey(attribute), ipAddress, accessDate, WSInvalidAccessReason.InvalidAccount);
}
public Cursor getStatsPercent(String startdate, String enddate) {
String query = "SELECT *, ROUND((count(sex)*100)/(SELECT count(sex) FROM salesTable)) AS '"+PERCENTAGE+"' FROM salesTable where timeStamp BETWEEN '"+startdate+"' AND '"+enddate+"' GROUP BY sex ORDER BY percentage DESC" ;
Cursor c = dbSales.rawQuery(query, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
Everything works fine but i always get back a Value under 100%.
I think it has to do with the ROUND but couldn't fix this.
public Cursor getStatsPercent(String startdate, String enddate) {
String query = "SELECT *, ROUND((count(sex)*100.0)/(SELECT count(sex) FROM salesTable)) AS '"+PERCENTAGE+"' FROM salesTable where timeStamp BETWEEN '"+startdate+"' AND '"+enddate+"' GROUP BY sex ORDER BY percentage DESC" ;
Cursor c = dbSales.rawQuery(query, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
I fixed it, just changed *100 to *100.0
So if anyone wants to calculate the percentage of the values from the database between dates this code should work.
I have two table BuildGroup and table DocumentTemplate. DocumentTemplate table has BuildGroupId as foreign key which is nullable. In a certain senario I update BuildGroupId in DocumentTemplate table.
public bool EditDocTempForBldGrp(int docId, int bldGrpId)
{
try
{
using (ISession session = Document.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
HSDocumentTemplate objDocBO = new HSDocumentTemplate();
objDocBO = GetDocumentDetailsById(docId);
HSBuildGroup objBldGrp = new HSBuildGroup();
if (bldGrpId != 0)
{
objBldGrp.Id = bldGrpId;
}
else
{
//int ? bldid = null;
//objDocBO.HSBuildGroup.Id = null;
//objDocBO.HSBuildGroup.Id = DBNull.Value;
//objDocBO.HSBuildGroup.Id = -1;
}
objDocBO.HSBuildGroup = objBldGrp;
session.Update(objDocBO);
transaction.Commit();
}
}
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
In another senario I need to set BuildGroupId in DocumentTemplate table again to
dbnull.value. I tried with different cases as in else block. It giving the error : Cannot
implicitly convert type 'System.DBNull' to 'int'.
How can I update a foreign key value with NULL? Any help will be appreciated.
A few observations:
You should not assign the Id to a HSBuildGroup object, but instead load the instance via Session.Load() in case the bldGrpId is not 0.
You can just set the build group of a document to null like this:
objDocBO.HSBuildGroup = null;
NHibernate will take care of the rest.
Hope that helps.
Use Session.Load and null as Kay Herzam said.
You must to be sure than the document exist to call session.Load. Example:
public bool EditDocTempForBldGrp(int docId, int bldGrpId)
{
try
{
using (ISession session = Document.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Get<HSDocumentTemplate>(docId).HSBuildGroup
= bldGrpId = 0 ? null : session.Load<HSBuildGroup>(bldGrpId);
transaction.Commit();
}
}
}
This way nhibernate will execute something like,
select ... from DocumentTemplate where DocId = ..;
UPDATE DocumentTemplate SET .... , BuildGroupId = null where DocumentId = XX;
or
select ... from DocumentTemplate where DocId = ..;
UPDATE DocumentTemplate SET .... , BuildGroupId = YY where DocumentId = XX;
Note there is no select for BuildGroup to the database.
If you are not sure about the existence of the build group, your code should look like:
public bool EditDocTempForBldGrp(int docId, int bldGrpId)
{
try
{
using (ISession session = Document.OpenSession())
using (ITransaction transaction = session.BeginTransaction())
{
session.Get<HSDocumentTemplate>(docId).HSBuildGroup
= session.Get<HSBuildGroup>(bldGrpId);
transaction.Commit();
}
}
}
This way nhibernate will execute something like,
select ... from DocumentTemplate where DocId = ..;
SELECT .... FROM BuildGroup where buildgroupid = ZZ;
UPDATE DocumentTemplate SET .... , BuildGroupId = null where DocumentId = XX;
Get automatically returns null if the object doesn't exist.
Finally you don't need to call Session.Update() this is for reattaching an entity. Everything associated to a Session will be flushed when you commit the transaction.