Sqlite trigger in android with an update - sqlite

When I am trying to achieve is a trigger that will update a table when an insert is made that should if the table has the articleId in place already the articleIsLiked should be changed to 0 and if not it should insert the articleId and the articleIsLiked to 1. Currently when I make an insert a new record is made each time I try to run an insert query instead of updating the record.
CREATE TRIGGER test_update
AFTER INSERT ON articlesTable
BEGIN
INSERT INTO articlesTable ( articleId, articleIsLiked)
VALUES(NEW.articleId, 1) ON DUPLICATE KEY UPDATE
articleIsLiked = 0;
END;
articlesTable
id PK
articleId int
articleIsLiked int

You cannot change an INSERT into an UPDATE with a trigger.
The easiest way to do this is in your code:
db.beginTransaction();
try {
ContentValues cv = new ContentValues();
long c = DatabaseUtils.queryNumEntries(db, "articlesTable",
"articleId = " + id);
if (c > 0) {
cv.put("articleIsLiked", 0);
db.update("articlesTable", cv, ""articleId = " + id, null);
} else {
cv.put("articleId", id);
cv.put("articleIsLiked", 1);
db.insert("articlesTable", null, cv);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}

Related

Android: Populating a GridtView from the SQLite Database

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);
}

Return identity of row inserted with sql stored procedure

I'm working on a legacy project and need to insert a row and return either that row or it's identity.
the new row is inserted with the correct values, only nothing is returned in the dataset when it gets back to .net.
I've tried selecting ##identity, RETURN, OUTPUT, but with everything i try the dataset is empty (but not null).
It's not the fault of MyUtils.DBHelper.GetDataSet, as this is used in other places and executes and returns ok.
USE [dbname]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Procedure [dbo].[DuplicateOrder]
(
#sourceid int,
#var1 int,
#var2 decimal(10,2),
)
AS
INSERT INTO OrderHeader (
Users_ID,
Stores_ID,
)
SELECT
#var1,
#var2
FROM Order
WHERE id = #sourceid
GO
The code i'm using to execute the stored procedure is:
Using cmd As New SqlCommand("DuplicateOrder") With {.CommandType = CommandType.StoredProcedure}
cmd.Parameters.AddWithValue("#sourceid", sourceId)
cmd.Parameters.AddWithValue("#var1 ", var1 )
cmd.Parameters.AddWithValue("#var2 ", var2 )
ds = MyUtils.DBHelper.GetDataSet(cmd)
End Using
This should do the trick:
ALTER Procedure [dbo].[DuplicateOrder]
(
#sourceid int,
#var1 int,
#var2 decimal(10,2)
)
AS
INSERT INTO OrderHeader (
Users_ID,
Stores_ID
)
SELECT
#var1,
#var2
SELECT ##IDENTITY AS ident
GO
I tested it on SQL server and it returns one row with the column ident.
have you tried executing this SELECT IDENT_CURRENT ('Table') AS Current_Identity; it should return the last generated identity in the current session and scope
##identity and return wouldn't work (SCOPE_IDENT(), IDENT_CURRENT() as well wouldn't work if you intend to insert multiple rows at once).
Your best bet is to use the OUTPUT but I don't see any OUTPUT in your code. Here is a sample for you (the code part is in C# but you can easily convert it, say using Telerik converter or write yourself - there are N ways to pass the data, I chose XML in this sample):
SQL code to generate sample table and procedure:
USE [Test];
GO
CREATE TABLE IdentityTest
(
Id INT IDENTITY
NOT NULL
PRIMARY KEY ,
FirstName VARCHAR(20) ,
LastName VARCHAR(20)
);
GO
CREATE PROCEDURE InsertTestData
(
#XML VARCHAR(MAX) ,
#NodeName VARCHAR(1000)
)
AS
BEGIN
DECLARE #myIDTable TABLE ( theID INT );
DECLARE #hDoc INT;
DECLARE #tbl TABLE
(
fName VARCHAR(20) ,
lName VARCHAR(20)
);
EXEC sp_xml_preparedocument #hDoc OUTPUT, #XML;
INSERT #tbl
SELECT *
FROM OPENXML(#hDoc, #NodeName, 1) WITH (fName VARCHAR(20), lName VARCHAR(20));
EXEC sp_xml_removedocument #hDoc;
INSERT INTO [IdentityTest] ( [FirstName], [LastName] )
OUTPUT [Inserted].[Id]
INTO #myIDTable
SELECT t.[fName], t.[lName]
FROM #tbl AS t;
SELECT *
FROM #myIDTable AS [mit];
END;
GO
And this is the C# code using the SP and inserting multiple rows and getting back their IDs (might have returned the full row data):
void Main()
{
List<Person> people = new List<Person> {
new Person { FName = "Sam", LName="Jones"},
new Person { FName = "Cetin", LName="Basoz"},
new Person { FName = "John", LName="Doe"},
new Person { FName = "Steven", LName="Smith"},
new Person { FName = "Bob", LName="Carpenter"},
};
for (int i = 0; i < 100; i++)
{
people.Add(new Person
{
FName = string.Format("FName#{0}", i),
LName = string.Format("LName#{0}", i)
});
}
var peopleAsXML = new XElement("People",
from p in people
select new XElement("Person",
new XAttribute("fName", p.FName),
new XAttribute("lName", p.LName)));
string sql = #"InsertTestData";
DataTable result = new DataTable();
using (SqlConnection con = new SqlConnection(#"server=.\SQLExpress2012;Trusted_Connection=yes;Database=Test"))
{
SqlCommand cmd = new SqlCommand(sql, con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#XML", peopleAsXML.ToString());
cmd.Parameters.AddWithValue("#NodeName", "/People/Person");
con.Open();
result.Load(cmd.ExecuteReader());
con.Close();
}
// check top 5 returned
for (int i = 0; i < 5; i++)
{
Console.WriteLine((int)result.Rows[i]["theID"]);
}
}
public class Person
{
public string FName { get; set; }
public string LName { get; set; }
}

Wrong query: Incorrect syntax near ')'

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.

How to check table is empty with count(*)

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).

how to read each value of a column in a table

Using x++ how to create a job to read each value of a column in a table in Microsoft dynamics AX 2009?
This code will display all the column values for a record.
static void Job1(Args _args)
{
DictTable dictTable = new DictTable(tableNum(CustTable));
DictField dictField;
int counter, fieldId;
CustTable custTable;
anytype value;
select firstonly custTable;
for (counter = 1; counter <= dictTable.fieldCnt(); counter++)
{
fieldId = dictTable.fieldCnt2Id(counter);
dictField = new DictField(tableNum(CustTable), fieldId);
if (!dictField.isSystem())
{
value = custTable.(fieldId);
if(value)
{
info(strFmt('%1 = %2',
dictField.label(),
any2str(value)));
}
}
}
}
For getting all the values for a specific column, please use Carlos Heuberger's code.
One possibility: in the AOT (Ctrl-D) right-click on Jobs and select New Job. In the new window enter something like (using the correct table and column name you want to read):
static void Job()
{
YourTable yourTable;
;
while select TheColumn from yourTable
{
// process yourTable.TheColumn
info(strFmt("value: %1", yourTable.TheColumn));
}
}
but thera are some other ways: Select Statements
Just a slight mod, took out any2str to make my table work:
strFmt('%1 = %2 \r\n', dictField.label(), value);

Resources