a sql query from oracle table - sql

I have only one column roll number in my oracle table. Lots of data are there in one column.
roll number
-------------
1
2
3
4
5
.
.
.
When i want to delete some roll numbers out of this table then i am writing:
delete from table name where roll number='2'; // 1 row deleted.
if i want to delete 5 from table then
delete from table name where roll number='5'; // 1 row deleted.
Similarly when i want to delete 100 records like this then i have to replace roll number field and it is quite time taking.
Is there any quick method how can i delete selective rows from the table?

If the ids to delete are consecutive you could use BETWEEN:
DELETE FROM your_table WHERE roll_number BETWEEN 5 AND 104
If not, you could use IN:
DELETE FROM your_table WHERE roll_number IN (5, 9, 110, ... )

You can get the list of number from another query and put it in a IN condition, so for example :
delete from table name where roll number IN (select roll number from table WHERE somecondition);

If u already know the range u can use Between else if u know the total numbers to be deleted then u can use IN like....
delete from table where roll number BETWEEN ....;

Related

Selecting records from PostgreSQL after the primary key has cycled?

I have a PostgreSQL 9.5 table that is set to cycle when the primary key ID hits the maximum value. For argument's sake, lets the maximum ID value can be 999,999. I'll add commas to make the numbers easier to read.
We run a job that deletes data from the table that is older than 45 days. Let's assume that the table now only contains records with IDs of 999,998 and 999,999.
The primary key ID cycles back to 1 and 20 more records have been written. I need to keep it generic so I won't make any assumptions about how many were written. In my real world needs, I don't care how many were written.
How can I select the records without getting duplicates with an ID of 999,998 and 999,999?
For example:
SELECT * FROM my_table WHERE ID >0;
Would return (in no particular order):
999,998
999,999
1
2
...
20
My real world case is that I need to publish every record that was written to the table to a message broker. I maintain a separate table that tracks the row ID and timestamp of the last record that was published. The pseudo-query/pseudo-algorithm to determine what new records to write is something like this. The IF statement handles when the primary key ID cycles back to 1 as I need to read the new record written after the ID cycled:
SELECT * from my_table WHERE id > last_written_id
PUBLISH each record
if ID of last record published == MAX_TABLE_ID (e.g 999,999):
??? What to do here? I need to get the newest records where ID >= 1 but less than the oldest record I have
I realise that the "code" is rough, but it's really just an idea at the moment so there's no code.
Thanks
Hmm, you can use the current value of the sequence to do what you want:
select t.*
from my_table t
where t.id > #last_written_id or
(currval(pg_get_serial_sequence('my_table', 'id')) < #last_written_id and
t.id <= currval(pg_get_serial_sequence('my_table', 'id'))
);
This is not a 100% solution. After all, 2,000,000 records could have been added so the numbers will all be repeated or the records deleted. Also, if you have inserts happening while the query is running -- particularly in a multithreaded environment.
Here is a completely different approach: You could completely fill the table, giving it a column for deletion time. So instead of deleting rows, you merely set this datetime. And instead of inserting a row you merely update the one that was deleted the longest time ago:
update my_table
set col1 = 123, col2 = 456, col3 = 'abc', deletion_datetime = null
where deletion_datetime =
(
select deletion_datetime
from my_table
where deletion_datetime is not null
order by deletion_datetime
limit 1
);

deleting from two tables in single script in sql

I have three tables xx_1 , xx_2, xx_3 such that :
xx_1
id obj_version_num location
1 x ubudu
2 x bali
3 x india
xx_2
id name grade
1 abc band 1
2 xyz band 2
3 gdgd band 3
xx_3 has :
Name details col1 p_id
abc A HDHD 10
xyz B HDHD 20
gdgd C HDHD 30
smith D HDHD 40
I want to delete data from xx_1 and xx_2 if the name is smith in xx_3
Currently i am doing :
delete from xx_1
where id in (select distinct id from xx_2 t ,xx_3 k
where t.name=k.name
and k.name ='Smith')
and then
delete from xx_2
where name ='Smith'
Is there anyway i can delete data from both these table together ? without creating two separate scripts ?
There is no way to delete from many tables with a single statement, but the better question is why do you need to delete from all tables at the same time? It sounds to me like you don't fully understand how transactions work in Oracle.
Lets say you login and delete a row from table 1, but do not commit. As far as all other sessions are concerned, that row has not been deleted. If you open another connection and query for the row, it will still be there.
Then you delete from tables 2, 3 and then 4 in turn. You still have not committed the transaction, so all other sessions on the database can still see the deleted rows.
Then you commit.
All at the same time, the other sessions will no longer see the rows you deleted from the 4 tables, even though you did the deletes in 4 separate statements.
EDIT after edit in question:
You can define the foreign keys on the 3 child tables to "ON DELETE CASCADE". Then when you delete from the parent table, all associated rows from the 3 child tables are also deleted.
You cannot delete from multiple tables in a single statement, primary key or not.

Data rows were repeated 4 times when I ( select first 1000 rows) In sql server

I use SQL Server 2014 to create a database and a table and inserted 10 rows of data.
The problem that when I select to 1000 rows, rows was repeated 4 times so they are now 40 rows as you can see in the images
Now I want to ask: why did this happen?
And how to solve that?
And also I want to ask how to find the query that I entered the data in .. I tried script table as > CREATE TO > create new query but it only gives me the table and values
How did you try and delete the rows? Did you write a DELETE statement and specify an id? Given you have 4 sets of rows that you say are unique (I'll take your word for it) and you have an ID column which repeats, you could adapt the following statement to help you.
DELETE TOP (3) FROM dbo.waqf WHERE ID IN (1,2,3,4,5,6,7,8,9,10)
EDIT
I made a mistake: Using the TOP (n) with an IN clause won't work as you might think - I should have tested it a bit. That will simply delete the first n rows in the table where the ID is in the specified range. Really you should loop through each of your unique IDs and issue a DELETE per id. There's probably a better way of doing this but it's early here and my brain isn't working yet.
DECLARE #id INT
SET #id = 1
WHILE #id <= (SELECT MAX(ID) FROM dbo.waqf)
BEGIN
DELETE TOP (3) FROM dbo.waqf WHERE ID = #id
SET #id += 1
END

DB2 - select last inserted 5 rows from a table

I have a table that has no indexed rows, nor a specific column...
Let's say "City, PersonName, PersonAge". I need to obtain the last 5 people inserted in that table...
How can I do it in in DB2?
I tried
select * from PEOPLE fetch first 5 rows only
this work perfectly... but no idea how to do it with the LAST rows....
You can't select the last 5 rows inserted, the database doesn't keep track of this. You need some sort of autoincremented ID or timestamp and order by that column descending.

Return rows in the exact order they were inserted

I have a simple join table with two id columns in SQL Server.
Is there any way to select all rows in the exact order they were inserted?
If I try to make a SELECT *, even if I don't specify an ORDER BY clause, the rows are not being returned in the order they were inserted, but ordered by the first key column.
I know it's a weird question, but this table is very big and I need to check exactly when a strange behavior has begun, and unfortunately I don't have a timestamp column in my table.
UPDATE #1
I'll try to explain why I'm saying that the rows are not returned in 'natural' order when I SELECT * FROM table without an ORDER BY clause.
My table was something like this:
id1 id2
---------------
1 1
2 2
3 3
4 4
5 5
5 6
... and so on, with about 90.000+ rows
Now, I don't know why (probably a software bug inserted these rows), but my table have 4.5 million rows and looks like this:
id1 id2
---------------
1 1
1 35986
1 44775
1 60816
1 62998
1 67514
1 67517
1 67701
1 67837
...
1 75657 (100+ "strange" rows)
2 2
2 35986
2 44775
2 60816
2 62998
2 67514
2 67517
2 67701
2 67837
...
2 75657 (100+ "strange" rows)
Crazy, my table have now millions of rows. I have to take a look when this happened (when the rows where inserted) because I have to delete them, but I can't just delete using *WHERE id2 IN (strange_ids)* because there are "right" id1 columns that belongs to these id2 columns, and I can't delete them, so I'm trying to see when exactly these rows were inserted to delete them.
When I SELECT * FROM table, it returns me ordered by id1, like the above table, and
the rows were not inserted in this order in my table. I think my table is not corrupted because is the second time that this strange behavior happens the same way, but now I have so many rows that I can delete manually like it was on 1st time. Why the rows are not being returned in the order they were inserted? These "strange rows" were definetely inserted yesterday and should be returned near the end of my table if I do a SELECT * without an ORDER BY, isn't it?
A select query with no order by does not retrieve the rows in any particular order. You have to have an order by to get an order.
SQL Server does not have any default method for retrieving by insert order. You can do it, if you have the information in the row. The best way is a primary key identity column:
TableId int identity(1, 1) not null primary key
Such a column is incremented as each row is inserted.
You can also have a CreatedAt column:
CreatedAt datetime default getdate()
However, this could have duplicates for simultaneous inserts.
The key point, though, is that a select with no order by clause returns an unordered set of rows.
As others have already written, you will not be able to get the rows out of the link table in the order they were inserted.
If there is some sort of internal ordering of the rows in one or both of the tables that this link table is joining, then you can use that to try to figure out when the link table rows have been created. Basically, they cannot have been created BEFORE both of the rows containing the PK:s have been created.
But on the other hand you will not be able to find out how long after they have been created.
If you have decent backups, you could try to restore one or a few backups of varying age and then try to see if those backups also contains this strange behaviour. It could give you at least some clue about when the strangeness has started.
But the bottom line is that using just a select, there is now way to get the row out of a table like this in the order they were inserted.
If SELECT * doesn't return them in 'natural' order and you didn't insert them with a timestamp or auto-incrementing ID then I believe you're sunk. If you've got an IDENTITY field, order by that.
But the question I have is, how can you tell that SELECT * isn't returning them in the order they were inserted?
Update:
Based on your update, it looks like there is no method by which to return records as you wish, I'd guess you've got a clustered index on ID1?
Select *, %%physloc%% as pl from table
order by pl desc