Insert row if not exists otherwise update sqlite - JavaScript - javascript

I know there have been a lot of questions on this in the past, but I seem to be unable to utilise those answers. I have tried, but they don't seem to work.
I have a table which stores two user inputted values: name and email. When they enter their name and e-mail, it gets stored into a single row of my table.
I want to be able to update this same row with a different name and email if the user types some other values, or insert these values if there weren't any previous values.
My code is here:
db.transaction(function(transaction) {
transaction.executeSql('INSERT INTO Details(name,email)\
VALUES(?,?)',[$('#entername').val(), $('#enteremail').val()],
nullHandler,errorHandler);
});
and the table creation is here if needed:
db.transaction(function(tx){
tx.executeSql( 'CREATE TABLE IF NOT EXISTS Details(Id INTEGER NOT\
NULL PRIMARY KEY,name,email)',
[],nullHandler,errorHandler);
},errorHandler,successCallBack);
I have tried using INSERT OR REPLACE, but this just creates a new row with new details and leaves the previous row there with the old details. Are there any efficient options relevant to my case? Thanks

Finally got it to work. I had to do this:
db.transaction(function(transaction) {
transaction.executeSql('INSERT OR REPLACE INTO Details(id,name,email)\
VALUES(1,?,?)',[$('#entername').val(), $('#enteremail').val()],
nullHandler,errorHandler);
});
where id is the row id. This replaces the first row with whatever else you type for name and email if it doesn't already exist

Related

delete associated records in Supabase

When using Supabase, is there a clean / simple way in which I can delete all associated records together with an item? Say I have Posts and a Post can have many Comments. When I delete the Post I want to delete the Comments as well.
Something like dependend: :destroy in Rails, basically.
const { data, error } = await supabase
.from('posts')
.delete()
.match({ id: 123 })
.options({ destroyDependent: true }) // set some option that tells Supabase to delete all associated records as well.
Yes, there is!
The magic happens not when you delete the data, but when you first create your comments table. It's also not a Supabase feature, but rather a postgres feature.
When you create a foreign key constraint, you can set a delete cascade option to tell the table to delete any related data.
For example, you can create a comments table like this:
create table if not exists public.comments (
id uuid not null primary key DEFAULT uuid_generate_v4 (),
post_id uuid references public.posts on delete cascade not null,
user_id uuid references public.users on delete cascade not null,
created_at timestamp with time zone default timezone('utc' :: text, now()) not null,
text varchar(320) not null
);
Notice the delete cascade keyword on post_id and user_id definition. Adding these will delete the comment entry if the related post or user is deleted.
Currently, there is no way of creating a column with delete cascade option in Supabase UI, so you would have to create such table using SQL.
Also, if you already have a table and would like to add this delete cascade option, you would have to remove the foreign key constraints and re-add it with delete cascade option. You can find out more about how to add delete cascade to an existing table here, but if your app is not in production, it might be easier to just delete the table and re-create it from scratch!
Edited
If you scroll a bit more to see the answer by #Justus Blümer, you can see how you can alter an existing table to add delete cascade!
Based on Tyler's tip here's how to change an existing key constraint to allow for a cascading deletion.
List all your foreign key constraints by executing this in the SQL editor in Supabase.
From there, identify the key that you need to change. Insert the name of the table with the items that you'd like to delete based on the deletion of a parent item in another table:
SELECT con.*
FROM pg_catalog.pg_constraint con
INNER JOIN pg_catalog.pg_class rel
ON rel.oid = con.conrelid
INNER JOIN pg_catalog.pg_namespace nsp
ON nsp.oid = connamespace
WHERE 1=1
AND rel.relname = 'YOUR_CHILD_TABLE';
Change the appropriate foreign key constraint (here: child_parent_id_fkey to support cascading deletes:
ALTER TABLE public.YOUR_CHILD_TABLE
DROP CONSTRAINT child_parent_id_fkey,
ADD CONSTRAINT child_parent_id_fkey
FOREIGN KEY (parent_id)
REFERENCES YOUR_PARENT_TABLE(id)
ON DELETE CASCADE;
This is what worked for me if you already have a table and need to alter it. in REFERENCES you need to mention 'public' before table. See example to understand
alter table
public.child drop constraint child_parent_id_fkey,
add
constraint child_parent_id_fkey
foreign key (parent_id)
references public.parent(id) on delete cascade;

array data insertion in mysql and prevent duplicate in node js [duplicate]

I've searched around but didn't find if it's possible.
I've this MySQL query:
INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8)
Field id has a "unique index", so there can't be two of them. Now if the same id is already present in the database, I'd like to update it. But do I really have to specify all these field again, like:
INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8)
ON DUPLICATE KEY UPDATE a=2,b=3,c=4,d=5,e=6,f=7,g=8
Or:
INSERT INTO table (id,a,b,c,d,e,f,g) VALUES (1,2,3,4,5,6,7,8)
ON DUPLICATE KEY UPDATE a=VALUES(a),b=VALUES(b),c=VALUES(c),d=VALUES(d),e=VALUES(e),f=VALUES(f),g=VALUES(g)
I've specified everything already in the insert...
A extra note, I'd like to use the work around to get the ID to!
id=LAST_INSERT_ID(id)
I hope somebody can tell me what the most efficient way is.
The UPDATE statement is given so that older fields can be updated to new value. If your older values are the same as your new ones, why would you need to update it in any case?
For eg. if your columns a to g are already set as 2 to 8; there would be no need to re-update it.
Alternatively, you can use:
INSERT INTO table (id,a,b,c,d,e,f,g)
VALUES (1,2,3,4,5,6,7,8)
ON DUPLICATE KEY
UPDATE a=a, b=b, c=c, d=d, e=e, f=f, g=g;
To get the id from LAST_INSERT_ID; you need to specify the backend app you're using for the same.
For LuaSQL, a conn:getlastautoid() fetches the value.
There is a MySQL specific extension to SQL that may be what you want - REPLACE INTO
However it does not work quite the same as 'ON DUPLICATE UPDATE'
It deletes the old row that clashes with the new row and then inserts the new row. So long as you don't have a primary key on the table that would be fine, but if you do, then if any other table references that primary key
You can't reference the values in the old rows so you can't do an equivalent of
INSERT INTO mytable (id, a, b, c) values ( 1, 2, 3, 4)
ON DUPLICATE KEY UPDATE
id=1, a=2, b=3, c=c + 1;
I'd like to use the work around to get the ID to!
That should work — last_insert_id() should have the correct value so long as your primary key is auto-incrementing.
However as I said, if you actually use that primary key in other tables, REPLACE INTO probably won't be acceptable to you, as it deletes the old row that clashed via the unique key.
Someone else suggested before you can reduce some typing by doing:
INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);
There is no other way, I have to specify everything twice. First for the insert, second in the update case.
Here is a solution to your problem:
I've tried to solve problem like yours & I want to suggest to test from simple aspect.
Follow these steps: Learn from simple solution.
Step 1: Create a table schema using this SQL Query:
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(30) NOT NULL,
`password` varchar(32) NOT NULL,
`status` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `no_duplicate` (`username`,`password`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
Step 2: Create an index of two columns to prevent duplicate data using following SQL Query:
ALTER TABLE `user` ADD INDEX no_duplicate (`username`, `password`);
or, Create an index of two column from GUI as follows:
Step 3: Update if exist, insert if not using following queries:
INSERT INTO `user`(`username`, `password`) VALUES ('ersks','Nepal') ON DUPLICATE KEY UPDATE `username`='master',`password`='Nepal';
INSERT INTO `user`(`username`, `password`) VALUES ('master','Nepal') ON DUPLICATE KEY UPDATE `username`='ersks',`password`='Nepal';
Just in case you are able to utilize a scripting language to prepare your SQL queries, you could reuse field=value pairs by using SET instead of (a,b,c) VALUES(a,b,c).
An example with PHP:
$pairs = "a=$a,b=$b,c=$c";
$query = "INSERT INTO $table SET $pairs ON DUPLICATE KEY UPDATE $pairs";
Example table:
CREATE TABLE IF NOT EXISTS `tester` (
`a` int(11) NOT NULL,
`b` varchar(50) NOT NULL,
`c` text NOT NULL,
UNIQUE KEY `a` (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
I know it's late, but i hope someone will be helped of this answer
INSERT INTO t1 (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
You can read the tutorial below here :
https://mariadb.com/kb/en/library/insert-on-duplicate-key-update/
http://www.mysqltutorial.org/mysql-insert-or-update-on-duplicate-key-update/
You may want to consider using REPLACE INTO syntax, but be warned, upon duplicate PRIMARY / UNIQUE key, it DELETES the row and INSERTS a new one.
You won't need to re-specify all the fields. However, you should consider the possible performance reduction (depends on your table design).
Caveats:
If you have AUTO_INCREMENT primary key, it will be given a new one
Indexes will probably need to be updated
With MySQL v8.0.19 and above you can do this:
mysql doc
INSERT INTO mytable(fielda, fieldb, fieldc)
VALUES("2022-01-01", 97, "hello")
AS NEW(newfielda, newfieldb, newfieldc)
ON DUPLICATE KEY UPDATE
fielda=newfielda,
fieldb=newfieldb,
fieldc=newfieldc;
SIDENOTE: Also if you want a conditional in the on duplicate key update part there is a twist in MySQL. If you update fielda as the first argument and include it inside the IF clause for fieldb it will already be updated to the new value! Move it to the end or alike. Let's say fielda is a date like in the example and you want to update only if the date is newer than the previous:
INSERT INTO mytable(fielda, fieldb)
VALUES("2022-01-01", 97)
AS NEW(newfielda, newfieldb, newfieldc)
ON DUPLICATE KEY UPDATE
fielda=IF(fielda<STR_TO_DATE(newfielda,'%Y-%m-%d %H:%i:%s'),newfielda,fielda),
fieldb=IF(fielda<STR_TO_DATE(newfielda,'%Y-%m-%d %H:%i:%s'),newfieldb,fieldb);
in this case fieldb would never be updated because of the <! you need to move the update of fielda below it or check with <= or =...!
INSERT INTO mytable(fielda, fieldb)
VALUES("2022-01-01", 97)
AS NEW(newfielda, newfieldb, newfieldc)
ON DUPLICATE KEY UPDATE
fielda=IF(fielda<STR_TO_DATE(newfielda,'%Y-%m-%d %H:%i:%s'),newfielda,fielda),
fieldb=IF(fielda=STR_TO_DATE(newfielda,'%Y-%m-%d %H:%i:%s'),newfieldb,fieldb);
This works as expected with using = since fielda is already updated to its new value before reaching the if clause of fieldb... Personally i like <= the most in such a case if you ever rearrange the statement...
you can use insert ignore for such case, it will ignore if it gets duplicate records
INSERT IGNORE
... ; -- without ON DUPLICATE KEY

PHP: How to remove/disable a selection from a checkbox group if the value is already selected and stored in database previously

Right now I am coding in PHP & HTML
I need to make a selection from the checkbox group
and it goes like this:
The value in the dropdown menu is retrieved from the value stored in the database in table subject. So the checkbox options will appears as (for example) Mathematics, Algebra, Calculus, English, Linguistic etc. -- I have no problem with displaying this one.
Table subject
subject_id subject_name
========== ============
1 Mathematics
2 Algebra
3 Calculus
4 English
5 Linguistic
So after that, a student can choose their subject and it will be stored in another table named student_subject where it stores the student_id and the subject_id (to store what subjects did a student chose)
Example:
table student_subject
student_id subject_id
========== ===========
1 1
1 2
1 3
2 1
2 3
Now, the student comes again to add another subject to his profile. The same checkbox option will be displayed as mentioned earlier in (1) but I would love to disabled/remove/not display the already selected option from being selectable again to avoid redundancy.
I really have no idea on how to create this function. I know there are a lot of experienced programmers and developera here so I wish you could show me the right way. Your guidance is highly appreciated.
You should not remove/disabled/not display the existing subjects.
First, you should check for existing rows for student_subject table and render it in HTML checkbox as selected.
Second, while student makes changes for subject selection in edit mode, check with the database rows with student and subject ids in a loop.
If submitted subject id for the student is not available in the database, insert that value to the table.
If submitted subject id for the student is available in the database, do nothing with it.
Check for the removed subject from submitted values with the database, and delete from the database.
If you want to disable existing subjects, use readonly to the checkbox if the subject is assigned to the student.
This is just an idea:
On your #2 where a table will store student_id and subject_id, I think it's best that whenever you store value to subject_id- you just serialize the value by storing it on an php array in that way you can iterate the whole array if the field was checked or not.
Json_encode is also good since it will be a string and same as serialize
Example:
Student_id Subject_ID
999-0518 a:{this is the serialize value };
Then when you query the result it will be serialize, then use unserialize function and do a loop to iterate the results, same goes when you json_encode; just perform json_decode() function and perform loop.
You can use a query which only picks up subjects which ID isn't in student_subject.
It would look something like:
SELECT * FROM `subject`
WHERE `subject_id` NOT IN (
SELECT `subject_id` FROM `student_subject` WHERE `student_id` = '1'
)
(you can ommit the inner where clause if you don't want this to be user specific)
and then build the <select> element based on the array returned from it.

Javascript array in SQL prepared statement

Here is what I am trying to do. I have a simple piece of java script code which takes the value of a checkbox and deletes the corresponding from the database.. Say that I have three options red, blue, yellow displayed and red is selected, the record for red will be deleted.
This code does it perfectly.
var n = $('input[type=checkbox]:checked').val();
db.transaction(function (tx) {
tx.executeSql('delete from details where name = ?',[n],function(){
alert('The event is successfully deleted');
});
});
But the requirement is to capture multiple checkbox selections as well (i.e) if both red and blue are selected or all the three are selected, the code must deleted the records of the selected values. I am able to capture the values selected in an array with the following piece of code.
var checkboxValues = $('.myCheckbox:checked').map(function() {
return $(this).val();
}).get();
Now i need to use this array of strings in a SQL statement. I tried the following piece of code but of no use.
db.transaction(function (tx) {
tx.executeSql('delete from details where name in (?)',[checkboxValues],function(){
alert('The event is successfully deleted');
});
A few other answers suggested me to convert the array object into a comma-seperated string using toString() and join() function but those did not quite help me. I doubt whether my SQL statement is correct. Pls someone help me. Thanks in advance !!
Maybe you could turn the function around so that it iterates over the returned values and preforms the db function for each in turn. Something along the lines of:
$(checkboxValues).each(function(tx){...
Or you could consider preforming the SQL update as each value is found within the first function, as long as you are throwing security out the window. Then you would only need to include the value as a this and you could lose the variable.

How to get the last record of the table and update a column value and insert to the same column with new record using angularJs/Javascript/Jquery

I am working in Web Api & MVC using angularjs for CURD operations,
In my DB I have a table "Accounts" it has a column with Name "ID" which will insert as
1 for first record and 2 for second record etc...
This column values will increment as per the last record in table,
this process should be in client side only.
Thanks in advance
If I understand your question correctly, you want to send next ID from db to client, create a new record on client with that ID and update it in db.
1) All you need to do is to create a empty record in db and send it's id/primary key to the client. This approach has a potential problem that, if the client stops/chooses to cancel the operation, there will be lot of empty records created.
2) Otherwise, you can fetch the last record from client using select max(id) from table and then use id+1 for the new record. The problem with this approach is that when multiple clients try to update db at the same time, all of them will/may have the same id.
3) In order to overcome the problem of (2), you can use locking mechanisms, but thats not how you do it. Its not worth it.
In my opinion, in most of the cases, client doesn't need to know the id of the going to be created record. Once the record is created, you can send it from db.
Once you're within the table, do everything in there. It's faster an easier.
UPDATE table1 SET column = (SELECT DISTINCT MAX(id) FROM Accounts WHERE user = ? GROUP BY id DESC LIMIT 1 ) WHERE user = ?

Categories

Resources