I am studying SQLite for Node.js. Currently I am at the very beginning.
I tried to insert row to a table but got error. The code I am using comes from this tutorial.
This is the code:
const sqlite3 = require('sqlite3').verbose();
let db = new sqlite3.Database('./database/sq-lite-data-base.db', (err) => {
if(err) {
return console.log(err.message);
}
console.log("Connected to database!")
});
// Create table named 'users' with two columns: 1 - 'name' which values to be of type "text",
// and "age" of type "integer"
// db.run('CREATE TABLE users(name text, age integer)'); //When this line is not connected I get different error: "The table users already exists"
// Insert two rows to table "users"
db.run('INSERT INTO users(name, age) VALUES("Riko", 29)', ['C'], (err) => {
if(err) {
return console.log(err.message);
}
console.log('Row was added to the table: ${this.lastID}');
})
The error I get is:
SQLITE_ERROR: no such table: users
Another thing that puzzles me is the second parameter of the function db.run. In my case I have passed the argument ['C']. But what does this argument do, or what is it designated for?
First you have to check the user table in your db '/database/sq-lite-data-base.db'.
If not:
db.run('CREATE TABLE users(name TEXT,age INT)');
And you have to change the code in above snippet like this
db.run('INSERT INTO users(name, age) VALUES(?, ?)', ['Raiko',29], (err) => {
if(err) {
return console.log(err.message);
}
console.log('Row was added to the table: ${this.lastID}');
})
You can also refer about sqlite tutorial.http://www.sqlitetutorial.net/sqlite-nodejs/insert/
Try creating the table users first, before inserting any data in it (this probably caused the error):
db.run('CREATE TABLE users(name)');
Then insert the data into the table by putting a questionmark as placeholder in VALUES. The second argument of db.run is then used to pass the actual name value to sqllite.
db.run('INSERT INTO users(name) VALUES(?)', ['Riko'])
You can also use a database browser to gain more insight as to why your having problems: http://sqlitebrowser.org/.
If you have to insert data for multiple columns with large data. see the query if you want good Ui for handling db.
use sqlitestudio for userface based Sqlite db view: SqliteStudio
firstly check db and table is exist or not.then insert multiple values :
var data=[
['Mungade','26'],
['Nagnath','27']
]
for (var i=0;i<data.length; i++){
db.run("INSERT INTO user(name,age) values(?,?)",data[i][0],data[i][1],(err,rows)=>{
if(err){
throw err;
}
console.log('Insert Success');
})
}
its working for me.
A possible answer might be that your DB is referenced incorrectly. If this is the case it will create an empty DB named 'databasesq-lite-data-base.db' and since this DB is empty it will not find the table.
So a connection will work but it will not be the DB you wanted it to be.
In your windows explorer look whether and empty DB with the above name was created somewhere.
you need to serialize it all.
It is not possible to do 2 things at the same time except if you serialize
db.serialize(() => {
db.run('CREATE TABLE users(name text, age integer)');
// Insert two rows to table "users"
db.run('INSERT INTO users(name, age) VALUES("Riko", 29)', ['C'], (err) => {
if (err) {
return console.log(err.message);
}
console.log('Row was added to the table: ${this.lastID}');
})
}
Related
SECOND EDIT
The issue was caused by the MAX_INTEGER_VALUE which is lower then the integer value I was passing. I changed the MySQL table column to TEXT instead of BIGINT and everything is being returned correctly.
Thanks for all the help!
EDIT
So I just realized that the userID variable and the guildID variables are being passed using this line of code.
mysqlModule.userCrewSearch(575783451018526744, 282997056438665217);
However the values that are being supplied to the SQL statement turn the last two digits of the number into '00'. So instead of 575783451018526744 the value being passed into the SQL statement is 575783451018526700.
So why is this value being changed when nothing I am doing in my code is changing these values?
Original Post
I'll keep this short and sweet. I'm trying to run a query using the nodejs MySQL package. I'm not sure where I'm going wrong but whenever I call my function that executes my query, I'm always returned an empty array, unless I hardcode the values into the SQL query.
Heres the code:
// Search for the User's Crew
function userCrewSearch(guildID, userID) {
pool.getConnection(function(err, connection) {
if(err) {
return console.log(err);
}
var sql = "SELECT * FROM `crew-members` WHERE `userID`=? AND `guildID`=?;";
console.log(sql);
connection.query(sql, [guildID, userID], function(err, results) {
connection.release(); // always put connection back in pool after last query
if(err) {
return console.log(err);
}
return console.log(results);
});
});
}
I'm calling this function like so: userCrewSearch(575783451018526744, 282997056438665217);
Both of the values I'm passing are integers. However this is what I get in my console.
However, here is my code with the values hardcoded into the SQL... to which the code then returns the result in the form of a RowDataPacket.
// Search for the User's Crew
function userCrewSearch(guildID, userID) {
pool.getConnection(function(err, connection) {
if(err) {
return console.log(err);
}
var sql = "SELECT * FROM `crew-members` WHERE `userID`=282997056438665217 AND `guildID`=575783451018526744;";
console.log(sql);
connection.query(sql, [guildID, userID], function(err, results) {
connection.release(); // always put connection back in pool after last query
if(err) {
return console.log(err);
}
return console.log(results);
});
});
}
Heres the result.
Bonus Question: How do I handle the RowDataPacket? Can I convert this directly into an object so I can call results.crewID and return just that value?
Same problem i was facing few days ago. I have solved this by converting the parameters into string.
function userCrewSearch(String(guildID), String(userID)) {
// your code here
}
Try adding + before your numeric parameter, it converts into number, it worked for me-
connection.query(sql, [+guildID, +userID], function(err, results) {
for your bonus questions answer, you can directly access the crewID or some other key using,
results[0].crewID
or do something like -
const [ result ] = results;
console.log(result.crewID)
i need to do a multiple row delete query with the where clause in list (id1,id2..)
But since we don't have lists in JS i'm having a problem with passing the parameters to the query.This is my code:
let list =[1,2,..];
let Query = 'DELETE FROM Table WHERE id IN (?)';
connection.query(Query,list, function (err, result) {
`enter code here`
};
when i pass it this way and after logging the mysql server to a Logfile i see that it actually passes only the first id.
PS : i tried without the parentheses around ? and also doing a Array.join on the list but both didn't work.
Read in document of https://github.com/mysqljs/mysql#performing-queries (if you use this lib to connect mysql)
let list =[1,2,..];
let Query = 'DELETE FROM Table WHERE id IN (?)';
// values param need is a array of value to binding to "?"
// you can try [list.toString()] if the block above not working
connection.query(Query,[list], function (err, result) {
`enter code here`
};
Simply append the list of items to the query string:
let list = [1, 2, 3];
let Query = `DELETE FROM Table WHERE id IN (${list})`;
connection.query(Query, function (err, result) {
`enter code here`
};
Unfortunately, ? placeholders don't work with the IN operator. So you should escape the values. Say the list variable is coming from an external source; so to prevent SQL Injection you can:
// `list` is filled in outside this process
const Query = `DELETE FROM Table WHERE id IN (${list.map((item) => connection.escape(item))})`;
connection.query(Query, function (err, result) {
// handle error or result here
};
I noticed that list.map(connection.escape) won't work and throw:
TypeError: Cannot read property 'config' of undefined
I am trying to create a table and insert a few data in it. First things first, I know .run is async, so I guess there is no prob since I have them inside the .get otherwise I know would get the error that the table doesn't exist on the first part of the code.
So where is my problem; I am inserting a few data into the table, and when I view it with a DB browser on my PC, everything appears fine!, but, when I run the code the row.uid, returned with the SELECT is not the one that's in the array.
I dont know if it matters but the uid I am trying to insert is a long integer, like: 212545136172336003 but instead I get back 212545136172336000, notice how the 3 is now 0 at the end. I am using the sqlite3 module.
var my_array = [uid1,uid2...];
db.serialize(function() {
db.run(`CREATE TABLE IF NOT EXISTS users (uid LONG PRIMARY KEY, value1 INTEGER, value2 INTEGER, value3 INTEGER)`);
my_array.forEach(id => {
db.get(`SELECT * FROM users WHERE uid='${id}'; `, (err, row) => {
if(row == undefined) db.run(`INSERT INTO users (uid, value1, value2, value3) VALUES ('${id}',0,0,0)`);
if(err) return;
});
});
});
//...
function my_f(uid, callback)
{
db.get(`SELECT * FROM users WHERE uid='${uid}';`, function(error, row) {
console.log(row.uid) // <----
if(row == undefined){
db.run(`INSERT INTO users (uid, value1, value2, value3) VALUES ('${uid}',0,0,0)`);
return callback([uid,0,0,0]);
}
if(error) return;
return callback([row.uid, row.value1, row.value2, row.value3]);
});
}
Currently working code: The first connection query adds a new user to the database using the information filled in the form, the second one inside the for loop checks the database if the interest already exists with the given name before it creates a new one. The missing part is the important one.
Problem: How can I link the new interest added to the database or an existent one if neither the user nor interest is created. I do understand that I need to run the two query below before I link them to make sure they exist, but how can I get the ID for the new user or the new interest? This all happens on the post request for a registration form.
connection.query('INSERT INTO User set ? ', [newUserData], function (err) {
if (err) { throw err; }
res.redirect('/');
});
let interests = {
userInterests: req.body.signupNewTagInterests.split(",")
}
for (let i = 0; i < interests.userInterests.length; i++) {
connection.query('SELECT title FROM Interest WHERE title =?', [interests.userInterests[i]], function (err, results) {
if (err) { throw err; }
if (typeof results[0] === 'undefined') {
connection.query('INSERT INTO Interest (title) Value(?) ', [interests.userInterests[i]], function (err) {
if (err) { throw err; }
});
}
});
}
Tabels:
User:
ID
first_name
etc...
Interest:
ID
title
User_Interests:
User_ID
Interest_ID
First you need to insert the user irrespective of where interest with interest id present or not.
Then you need to insert interest into interest table if not present
Once above part is completed then you can link these two things with interest title and then insert new records in user interest table.
vice versa for interest.
If you want to get an id as it's entered you can use the following query:
SELECT LAST_INSERT_ID();
or via having your framework/MySQL library (in whatever language) call
mysql_insert_id()
right after a query. You can then use that as your user_id checking in the interests database.
How to insert two table in one time?
I need to insert second table user_information the field user_id with first table user insert returning id, I found this answer but I can't find how to be with params prepared statements
var dbQuery = 'WITH insertUser AS (
INSERT INTO "user" (status, create_date) VALUES ($1, $2) RETURNING id
)
, insertUserInformation AS (
INSERT INTO user_information (user_id, email) VALUES ($3, $4)
)
';
yield queryPromise(dbClient, dbQuery, [status, timestamp, ??, email]);
pg
Use transactions. That way either all queries will be committed, or none will be committed. And the incomplete state before you have executed all queries is not visible for other processes.
More on how to do transactions in node-postgres is available at https://github.com/brianc/node-postgres/wiki/Transactions
And for reference the most relevant section is:
var Client = require('pg').Client;
var client = new Client(/*your connection info goes here*/);
client.connect();
var rollback = function(client) {
//terminating a client connection will
//automatically rollback any uncommitted transactions
//so while it's not technically mandatory to call
//ROLLBACK it is cleaner and more correct
client.query('ROLLBACK', function() {
client.end();
});
};
client.query('BEGIN', function(err, result) {
if(err) return rollback(client);
client.query('INSERT INTO account(money) VALUES(100) WHERE id = $1', [1], function(err, result) {
if(err) return rollback(client);
client.query('INSERT INTO account(money) VALUES(-100) WHERE id = $1', [2], function(err, result) {
if(err) return rollback(client);
//disconnect after successful commit
client.query('COMMIT', client.end.bind(client));
});
});
});
It's impossible in postgresql. I solved exact the same problem by creating function and simply executing with parameters. As I see in your table structure, you don't have many attributes, so this will be relatively easy.
Example code:
function.sql
CREATE OR REPLACE FUNCTION createSomething
(
IN attr1 VARCHAR(20),
IN attr2 VARCHAR(200)
)
RETURNS void AS $$
DECLARE userId INTEGER;
BEGIN
INSERT INTO table1 (col1, col2) VALUES
(
attr1,
attr2
) RETURNING id INTO userId;
INSERT INTO table2 (user_id, col11, col2) VALUES
(
userId,
col11,
col12
);
END;
$$ LANGUAGE plpgsql;
Usage:
SELECT createSomething('value1', 'value2');
Please notice, that second insert statement will know what was recently user's id and will use it.
PostgreSQL Prepared Statements will not let you do it. You will have to use a transaction.
Below is your example implemented with pg-promise, using ES7 syntax:
const pgp = require('pg-promise')({
// initialization options;
});
const db = pgp(/* your connection object or string */);
db.tx(async t => {
const user = await t.one('INSERT INTO user(status, create_date) VALUES($1, $2) RETURNING id', [status, timestamp]);
return t.none('INSERT INTO user_information(user_id, email) VALUES($1, $2)', [user.id, email]);
})
.then(() => {
// SUCCESS;
})
.catch(error => {
// ERROR;
});
I do not believe this can be accomplished as a natural sql statement. You have to wrap it up as a procedure or some other mechanism.