In a Node webkit App, WEB SQL API is not creating a database - sqlite

I'm creating a database and a table for my node webkit app, using this :
var db = openDatabase('vizDb', '1.0', 'Visualiation database', 2 * 1024 * 1024);
db.transaction(function (tx) {
query = 'CREATE TABLE IF NOT EXISTS dataworking (id, ACV, sales, Date)';
tx.executeSql(query);
$.each(records, function(i,thisRecord){
records[i] = thisRecord.split(',');
query = 'INSERT INTO dataworking (id, ACV, sales, Date) VALUES (' + thisRecord + ')';
//console.log(query); //query is correct here
tx.executeSql(query);
});
});
But when I do the following, I don't get the records in the console.
db.transaction(function (tx) {
query = 'SELECT * FROM dataworking';
tx.executeSql(query , [], function (tx, results) {
var len = results.rows.length ;
for (i = 0; i < len; i++) {
console.log(results.rows.item(i));
}
});
});
I want to check if my records are entered currently. For this, I go to the location
..AppData\Local\Package-name\databases and I see a file Databases.db and a folder file__0 with a file named '1'. I run the SQLite prompt from the location ../file__0/ and list the tables
sqlite>.open 1
sqlite>.tables
sqlite> __WebKitDatabseInfoTable__
But there is no table named dataworking.
How do I open the database vizDb and check if the table 'dataworking' is made?

The Databases.db file contains a list of the actual databases.
Your database is in the file 1.

Related

how to use upsert in react native sqlite database

I have a table in react native SQLite with 2 columns app_name,key
I want to update a value if it exists based on app_name else insert new data I tried the following
db.transaction(function (tx) {
tx.executeSql(
'Insert or Ignore Into client_registration (app_name, key) values(?,?); UPDATE client_registration SET app_name=?, key=? where changes() = 0 and "app_name" = ?;',
['coin', 123],
(tx, results) => {
if (results.rowsAffected > 0) {
console.log('success')
);
} else console.log('Registration Failed');
},
);
});
i am unable to ge any output .
SQLite supports UPSERT with the ON CONFLICT clause:
INSERT INTO client_registration(app_name, key) VALUES (?, ?)
ON CONFLICT(app_name) DO UPDATE
SET key = EXCLUDED.key;
I assume that for app_name there is a unique constrain defined in the table.
You will have to check the version of SQLite that your android API level uses, because UPSERT was introduced in version 3.24.0
Without the use of UPSERT you will have to execute 2 statements in this order:
UPDATE client_registration
SET key=?
WHERE app_name = ?;
INSERT OR IGNORE INTO client_registration(app_name, key) VALUES (?, ?);

Can SQLite return the id when inserting data?

I'm using sqlite3.exe to execute queries against my DB, using the following code.
public static string QueryDB(string query)
{
string output = System.String.Empty;
string error = System.String.Empty;
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "C:\\sqlite\\sqlite3.exe";
startInfo.Arguments = "test.db " + query;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
try
{
using(System.Diagnostics.Process sqlite3 = System.Diagnostics.Process.Start(startInfo))
{
output = sqlite3.StandardOutput.ReadToEnd();
error = sqlite3.StandardError.ReadToEnd();
sqlite3.WaitForExit();
}
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.ToString());
return null;
}
return output;
}
I'm inserting data into a table, and I'd like it to return the id of the inserted data. Is there a way to get SQLite to do this?
For example, my query might look like this "INSERT INTO mytable (some_values) VALUES ('some value');". After this query is run, I'd like output to contain the rowid of the inserted data. Is there any way to do this (a command line switch, etc.)?
A possible workaround, is to run two commands against the DB. First insert the data, then get the last inserted row id. In which case, the query would look like this "\"INSERT INTO mytable (some_values) VALUES ('some value'); SELECT last_insert_rowid();\""
You should not use max(id) or similar function in DB.
In this specific case it can work, under the condition that you use ONE connection and ONE thread to write data to DB.
In case of multiple connections you can get wrong answer.
From version SQLite 3.35.0 it supports returning close in the insert statement (SQLite Returning Close)
create table test (
id integer not null primary key autoincrement,
val text
);
insert into table test(val) values (val) returning id;
Would you consider this:
select max(id) from your_table_name;
or embedded function last_insert_rowid()?

How to insert value using textfield to get data in sqlite using appcelerator

I beginner in using appcelerator to develop android apps. I tried to insert data using textfield to retrieve data in sqlite. but if I use example "doc_num.value" with query. I will get error "[ERROR] : V8Exception: Exception occurred at test/csv.js:61: Uncaught TypeError: Cannot read property 'value' of undefined"
var currentWin = Ti.UI.currentWindow;
var label_export = Ti.UI.createLabel({
color:'#fffdfd',
text: 'Please insert document number to export :',
textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER,
top: 20, //200
width: 300,
font:{fontFamily:'Arial',fontSize:14}
});
currentWin.add(label_export);
var doc_num = Ti.UI.createTextField({
color:'#fffdfd',
top:60,
left:10,
width:'80%',
height:40,
hintText:'Document Number',
keyboardType:Ti.UI.KEYBOARD_DEFAULT,
borderStyle:Ti.UI.INPUT_BORDERSTYLE_ROUNDED
});
currentWin.add(doc_num);
// btn search
var btn_search = Ti.UI.createButton({
title:'Export CSV',
top:55, //355
right:5,
width:'15%',
height:50,
color:'green',
borderRadius:1,
font:{fontFamily:'Arial',fontWeight:'bold',fontSize:8}
});
btn_search.addEventListener('click',function(e) {
var db = Ti.Database.install('../products.sqlite','products');
var dbName = db.execute('SELECT doc_num,barcode, product_name,oum,rack_loc,qty FROM products WHERE doc_num = ?',doc_num.value);
while (dbName.isValidRow()) {
var doc_num = dbName.fieldByName('doc_num');
var barcode = dbName.fieldByName('barcode');
var product_name = dbName.fieldByName('product_name');
var rack_loc = dbName.fieldByName('rack_loc');
var oum = dbName.fieldByName('oum');
var qty = dbName.fieldByName('qty');
dbName.next();
Ti.API.info(doc_num + ' ' + barcode + ' ' + product_name+' ' + rack_loc +' '+ oum +' '+qty);
}
dbName.close();
});
currentWin.add(label_warning);
currentWin.add(btn_search);
And this my table structure that I use for my database.Database name products and tape name also products
CREATE TABLE products (id INTEGER PRIMARY KEY, doc_num VARCHAR, product_name VARCHAR, barcode VARCHAR, rack_loc VARCHAR, oum VARCHAR, qty NUMERIC)
You just need to use this line of code instead of yours:
var dbName = db.execute('SELECT doc_num,barcode, product_name,oum,rack_loc,qty FROM products WHERE doc_num = ?', doc_num.value);
You cannot concatenate strings in execute method, you will need to standard approach of passing parameters in SQL query using '?' sign.
Also note that you cannot do this something like this also:
var query = 'select * from products where doc_num = ' + doc_num.value;
This query will fail in case where there are spaces in doc_num.value
So the recommended and safest way of passing values to queries is this:
var query = 'select * from products where doc_num = ? and someother_condition = ?';
db.execute(query, doc_num.value, someother_value);
db.execute method can take any number of parameters starting from 2nd parameter.

SQLite count and get other records in Cordova

Snippet of my code:
var sql = "SELECT name,data, COUNT(name) as 'mycount' FROM floodMaps WHERE name='?' GROUP BY name,data";
db.transaction(function(tx) {
tx.executeSql(sql,[flodMapName], function(tx,res){
//console.log(res.rows.item(0).data);
console.log(res.rows.item(0).mycount);
if(res.rows.item(0).mycount > 0) {
console.log('GETTING DATA FROM DB...');
It throws an error:
a statement with no error handler failed: Cannot bind argument at index 1 because the index is out of range. The statement has 0 parameters.
I am trying to count at the same time get the data from a table but unfortunately it's not working. I did my research, I haven't found a good documentation for the plugin.
This is how I created the table:
document.addEventListener("deviceready", function(){
//database
db = window.sqlitePlugin.openDatabase({name: 'demo.db', location: 'default'});
db.transaction(function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS floodMaps (name text primary key, data text)');
tx.executeSql('DELETE FROM floodMaps');
}, function(error) {
console.log('Create Table ERROR: ' + error.message);
}, function() {
console.log('Table created successfully.');
});
//end database
}, false);
The whole code is here.
I believe that the ? parameter placeholder should not be in single quotes. Try this instead:
var sql = "SELECT name, data, COUNT(name) as `mycount` FROM floodMaps WHERE name= ? GROUP BY name, data";
I guess you need not have to use single quote at all for alias. You can use as follows:
SELECT name,data, COUNT(name) as mycount FROM floodMaps WHERE name=?
Check out this official link that has sample for count query too.

Flex: sqlite last_insert_rowid over multiple insert calls

I have file with multiple SQL statements in it to be executed.
INSERT INTO reports (a,b,c) VALUES (1,2,3);
INSERT INTO units (report_id, e, f, g) VALUES ( (SELECT last_insert_rowid() FROM reports), 4, 5, 6);
INSERT INTO elements (report_id, h, i, j) VALUES ( (SELECT last_insert_rowid() FROM reports), 7, 8, 9);
The FROM reports section of the sub-selection does nothing.
What ends up happening is:
A row is inserted into reports and the reports.id field is autoincremented
A row is inserted into units with report_id being equal to the reports id
A row is inserted into elements with report_id being equal to units.id of the last row inserted
This is works as described in the sqlite documentation.
My issue is that I want all the queries subsequent to the report insert to use report.id.
Is there anyway I can get this to work on the database end without having to resort to a solution in as3?
There is a way to do this, but it is in AS3 using parameters.
What is done is instead of using the SELECT last_insert_row() function in each call, replace it with a parameter.
INSERT INTO elements (report_id, h, i, j) VALUES (#id, 7, 8, 9);
Now in my code I have to split the file into an array so that each individual queries is process separately (this is how AS3 implements sqlite's API).
var sqlArray:Array = sql.split(";\n\n");
Now what I do is execute the first statement for importing the report itself.
statement.text = sqlArray[0];
statement.execute();
Now the fun part. You need to get the id back out. So we run another query.
statement.text = "SELECT last_insert_rowid() as ID";
statement.execute();
var id:int = statement.getResult().data[0].id;
Now we can loop through the rest of the queries using the id as a parameter.
for(var i:int = 1; i < sqlArray.length - 1; i++) {
/**
* start at 1 because we already inserted the report
* end at length -1 because our last entry is empty because of how split works on our data
**/
statement.text = sqlArray[i];
statement.parameters['#ID'] = id;
statement.execute();
}
This is a little more complicated, but not much and it ends up working.
Everything rolled together into a single function (omitting a lot of class overhead) would be:
function importFromSQLString(sql:String):void {
try{
connection.begin();
var sqlArray:Array = sql.split(";\n\n");
statement.text = sqlArray[0];
statement.execute();
statement.text = "SELECT last_insert_rowid() as ID";
statement.execute();
var id:int = statement.getResult().data[0].id;
for(var i:int = 1; i < sqlArray.length - 1; i++) {
statement.text = sqlArray[i];
statement.parameters['#ID'] = id;
statement.execute();
}
connection.commit();
statement.clearParameters();
} catch (e:Error) {
connection.rollback(); //cleanup if there was a failure
}
}

Resources