This question already has answers here:
SQLite INSERT - ON DUPLICATE KEY UPDATE (UPSERT)
(5 answers)
SQL: How to update or insert if doesn't exist?
(2 answers)
Closed 9 years ago.
I have an sql table with 3 columns, none of which is UNIQUE ( but the pair name + role is ):
Name | Role | Votes
What I need to do is, write an sqllite query that stick to the following rules :
If a row with the given name and role already exist, votes is
incremented by 1
If not, a new row is created with Votes = 1
I've looked into INSERT OR REPLACE and this great post but it doesn't seem to help me that much, and I'm not even sure INSERT OR REPLACE is a viable option, since something like
INSERT OR REPLACE INTO words (name,role,votes)
VALUES ('foo','bar', coalesce((
select votes from words where name = 'foo' and role='bar'),0)+1)
always insterts and never replace
You simply need to create unique index over your 2 columns for this to work:
CREATE UNIQUE INDEX words_name_role_idx ON words (name,role)
Note that you do not create unique index for any single column, but for combination of 2 as a whole.
After that, your REPLACE INTO statement should start working correctly:
REPLACE INTO words (name,role,votes) VALUES ('foo','bar',
coalesce((
SELECT votes FROM words
WHERE name = 'foo' AND role='bar'),0
)+1
)
(note that I have changed counter to votes above).
This query will update your record with +1.
update todo set text='raj',complete='raj',pk=((SELECT pk FROM todo where text='raj' and complete='raj')+1) where (SELECT pk FROM todo where text='raj' and complete='raj')
EDIT YOUE QUERY
update words set name='foo',role='bar', votes =((SELECT votes FROM words where name='foo' and role='bar')+1) where (SELECT votes FROM words where name='foo' and role='bar')
And make insert query if this condition will not true.
Related
This question already has answers here:
How to select all records from one table that do not exist in another table?
(15 answers)
Closed 1 year ago.
I have one table "Cells" with Primary key "Cell_ID". There are 160 ID's/records. There is one other table, for example "Customers" where I use a field "CellID", which is a table list using row source the field "Cell_ID" from the table "Cells".
I would like to create a query that will return me all the Cell_ID values that are not used on the Customers.CellId field.
My first thought was to use something like the following:
SELECT Cells.Cell_ID
FROM Cells
WHERE Cells.Cell_ID NOT IN (
SELECT Customers.CellID
FROM Customers);
Your method is conceptually okay. But there is a problem if Customers.CellId is ever NULL. If that is the case, then the query will return no rows.
For this reason, I recommend never using NOT IN with a subquery. Instead, use NOT EXISTS:
SELECT c.Cell_ID
FROM Cells as c
WHERE NOT EXISTS (SELECT 1
FROM Customers as cu
WHERE c.Cell_ID = cu.CellID
);
This question already has answers here:
Can you SELECT everything, but 1 or 2 fields, without writer's cramp?
(12 answers)
Closed 5 years ago.
I am using Oracle Database and I need to realize a query which retrieves all the values of a table record (for a specific WHERE condition), except for one which is known.
Imagine to have the following table:
Sample table
Where you do not want to retrieve the "Age" column, but where - in next releases of the software - the table could have more columns respect to the ones actually present.
Is there any command in Oracle which excludes a specific column (always known, as in the example "Age") and allows me to retrieve all the other values?
Thanks in advance!
You can make that particular column Invisible using following query:
alter table TABLE_NAME modify COLUMN_NAME INVISIBLE;
This will exclude that column from select * statement unless and until you specify that particular column in select clause like below:
select COLUMN_NAME from TABLE_NAME;
From Your sample data:
alter table SAMPLE_TABLE modify Age INVISIBLE;
select * FROM SAMPLE_TABLE will produce
select FirstName, LastName, Address, City, Age from SAMPLE_TABLE will produce:
There are several approaches
1)You can set column UNUSED.It won't be retrieved (and it wont be used) with the queries. This would be permanent. You can't get then column back, the only allowed op would be DROP UNUSED COLUMNS.
ALTER TABLE sample_table SET UNUSED(age);
2)You can set column INVISIBLE, this is temporary. It won't be retrieved, unless you explicitly reference it in SELECT query.
ALTER TABLE sample_table MODIFY age INVISIBLE;
// to change it back to VISIBLE
ALTER TABLE sample_table MODIFY age VISIBLE;
3)Create VIEW without age column and then query view instead of querying TABLE.
CREATE VIEW sample_table_view AS
SELECT first_name, last_name, address, city FROM sample_table;
I'm trying to make a blog system of sort and I ran into a slight problem.
Simply put, there's 3 columns in my article table:
id SERIAL,
category VARCHAR FK,
category_id INT
id column is obviously the PK and it is used as a global identifier for all articles.
category column is well .. category.
category_id is used as a UNIQUE ID within a category so currently there is a UNIQUE(category, category_id) constraint in place.
However, I also want for category_id to auto-increment.
I want it so that every time I execute a query like
INSERT INTO article(category) VALUES ('stackoverflow');
I want the category_id column to be automatically be filled according to the latest category_id of the 'stackoverflow' category.
Achieving this in my logic code is quite easy. I just select latest num and insert +1 of that but that involves two separate queries.
I am looking for a SQL solution that can do all this in one query.
This has been asked many times and the general idea is bound to fail in a multi-user environment - and a blog system sounds like exactly such a case.
So the best answer is: Don't. Consider a different approach.
Drop the column category_id completely from your table - it does not store any information the other two columns (id, category) wouldn't store already.
Your id is a serial column and already auto-increments in a reliable fashion.
Auto increment SQL function
If you need some kind of category_id without gaps per category, generate it on the fly with row_number():
Serial numbers per group of rows for compound key
Concept
There are at least several ways to approach this. First one that comes to my mind:
Assign a value for category_id column inside a trigger executed for each row, by overwriting the input value from INSERT statement.
Action
Here's the SQL Fiddle to see the code in action
For a simple test, I'm creating article table holding categories and their id's that should be unique for each category. I have omitted constraint creation - that's not relevant to present the point.
create table article ( id serial, category varchar, category_id int )
Inserting some values for two distinct categories using generate_series() function to have an auto-increment already in place.
insert into article(category, category_id)
select 'stackoverflow', i from generate_series(1,1) i
union all
select 'stackexchange', i from generate_series(1,3) i
Creating a trigger function, that would select MAX(category_id) and increment its value by 1 for a category we're inserting a row with and then overwrite the value right before moving on with the actual INSERT to table (BEFORE INSERT trigger takes care of that).
CREATE OR REPLACE FUNCTION category_increment()
RETURNS trigger
LANGUAGE plpgsql
AS
$$
DECLARE
v_category_inc int := 0;
BEGIN
SELECT MAX(category_id) + 1 INTO v_category_inc FROM article WHERE category = NEW.category;
IF v_category_inc is null THEN
NEW.category_id := 1;
ELSE
NEW.category_id := v_category_inc;
END IF;
RETURN NEW;
END;
$$
Using the function as a trigger.
CREATE TRIGGER trg_category_increment
BEFORE INSERT ON article
FOR EACH ROW EXECUTE PROCEDURE category_increment()
Inserting some more values (post trigger appliance) for already existing categories and non-existing ones.
INSERT INTO article(category) VALUES
('stackoverflow'),
('stackexchange'),
('nonexisting');
Query used to select data:
select category, category_id From article order by 1,2
Result for initial inserts:
category category_id
stackexchange 1
stackexchange 2
stackexchange 3
stackoverflow 1
Result after final inserts:
category category_id
nonexisting 1
stackexchange 1
stackexchange 2
stackexchange 3
stackexchange 4
stackoverflow 1
stackoverflow 2
Postgresql uses sequences to achieve this; it's a different approach from what you are used to in MySQL. Take a look at http://www.postgresql.org/docs/current/static/sql-createsequence.html for complete reference.
Basically you create a sequence (a database object) by:
CREATE SEQUENCE serials;
And then when you want to add to your table you will have:
INSERT INTO mytable (name, id) VALUES ('The Name', NEXTVAL('serials')
This question already has answers here:
Can you SELECT everything, but 1 or 2 fields, without writer's cramp?
(12 answers)
Closed 8 years ago.
I have a table with many columns (20 or 25) and i want to build an insert statement on it, using select and generating another primary key
The simple soulution will be:
INSERT INTO myTable
SELECT mySeq.nextVal PRIMARY_KEY, COLUMN2, COLUMN3, COLUMN4...
FROM myTable
WHERE PRIMARY_KEY = 1
Since my table have many columns, there is a way to say "i give you primary key, and ALL the other columns are the same" without explain them?
Like:
INSERT INTO myTable
SELECT mySeq.nextVal m.* /* Sure this not work because i get again PRIMARY_KEY column*/
FROM myTable m
WHERE PRIMARY_KEY = 1
There is no way to specify something like SELECT * EXCEPT aColumn, you will have to write them manually as you already did, sorry.
Actually, you could do a subquery that select column from table info then query that subquery but that make non-sense to me.
If your table contains so many column that it is a pain to write them all, then you might want to re-design your database and split your table in multiple tables.
This question already has answers here:
MySQL: How to copy rows, but change a few fields?
(8 answers)
Closed 5 years ago.
How would I copy entire rows within a table and change one value?
insert into user (
user_id,account_id,user_type_cd,name,e_mail_addr,
login_failure_cnt,admin_user,primary_user
)
select * from pnet_user where account_id='1'
But now I want to change 1 to 2 on the inserted entries.
But now I want to change 1 to 3 on the inserted entries.
But now I want to change 1 to .... on the inserted entries.
But now I want to change 1 to 1000 on the inserted entries.
It will copy and write down 1000 times (only changing id ).
I'm not completely sure I understand what you're asking. If you want to copy the records where Account_ID = 1 into new rows and change Account_ID to 2 (or whatever number), this should work for you:
insert into user (user_id,account_id,user_type_cd,name,e_mail_addr,
login_failure_cnt,admin_user,primary_user)
select user_id,2,user_type_cd,name,e_mail_addr,
login_failure_cnt,admin_user,primary_user
from pnet_user where account_id='1'
Basically, replace Account_ID with the value 2. If Account_ID is a varchar, use single quotes around it instead.