Delete all rows from a table that are present in a View - sql

The queries I would like to perform:
BEGIN TRANSACTION
INSERT INTO TABLE_B SELECT * FROM TABLE_A WHERE SOME_COLUMN = 'something'
DELETE FROM TABLE_A WHERE COLUMN IN (
SELECT * FROM TABLE_A WHERE SOME_COLUMN = 'something'
)
END TRANSACTION
As you can see, there is a redundant SELECT statement in the DELETE query that I would like to replace (if possible), thus improving efficiency.
I was thinking to create a View with the rows in the first query and then scan the View with the rows in the second table. If some condition matches, then delete the row from the second table.
Could I get some pointers on how this could be done? If there is anything wrong I am doing, please criticize.

This is what you want, I think:
delete from table_a
where some_column = 'something'
As written, your query would probably generate a syntax error. The "SELECT *" would return all columns in table_a, and it presumably has more than one column.

Generally, you should be able to do joins in the delete statement, but you'd need to specify the table from which you're deleting rows:
delete table_a
from table_a left join table_b on (table_a.column_a = table_b.column_b)
where table_b.column_b = 'some_value'

Related

visual foxpro 9.0, how to find/get repeated records

I have a table with 2001233 records.
I can use 'Select distinct * from that_table' to get all records not repeated.
Maybe about 2001100 records.
How to get those 133 records into another table if I want to check the records disappeared after 'distinct'.
Another question is
When appending new records from one table to another table, how to check that the appended record is not already in the target table?
thanks for answering my question :)
It would be a hack and slow for 2+ million rows but you can do this:
Select Sys(2017,'',0,3) As crc, * ;
from myTable Into Cursor crsTemp ;
nofilter
Select * From crsTemp ;
where crc In ;
( Select crc From crsTemp;
having Count(*) > 1 ;
group By crc) ;
into Cursor crsDupes ;
nofilter
Select crsDupes
Browse
You should have used primary key from the start.
For your second question, I think it is best to use "insert into" rather than append. i.e.:
Insert into tableA ;
select * from tableB t1 ;
where not exists ( ;
select * from tableA t2 ;
where t1.field1 = t2.field1 and t1.field2 = t2.field2)
Here is another way to find the duplicate records:
Assuming that you don't keep deleted records hanging around...
select tableA
set deleted off
delete all
index on <key expression> to keyfield unique
set deleted on
recall all
browse for deleted
This process will delete all the records, and the recall statement will only apply to the indexed records, leaving the duplicates tagged as deleted.
Try this to check if there is a duplicate record.
SELECT colName, count(*) FROM tblName GROUP BY colName HAVING count(*) > 1

Delete a record when no corresponding record exists in first table

How can I delete non matching rows from a table? I have two tables that have a majority of related records. Table A must exist in table B. If table B record does not exist in table A delete table B record.
I am hoping there is a method to do this with a query rather then coding to populate a datatable and interating through each reocrd to see if there is a match.
TableA
keyID,
foreignID,
text
TableB
keyID,
recordID,
text
foriegnID and recordID are the related fields. I did not design these tables.
Somethins like this....
DELETE * FROM TableB WHERE (SELECT [foreignID] FROM TableA) <> recordID;
UPDATE: I can retireve the records needing to be deleted with query, but I would like to just delete them.
SELECT * FROM TableA LEFT JOIN TableB ON TableA.[foreignID] = TableB.[recordID] WHERE (((TableB.recordID) Is Null));
I am using vb.net to process a series of Access database.
You can use the DCount Function in Access SQL, and it will work regardless of whether the query is run from within an Access session or externally from VB.Net or other client code.
Start with a SELECT query to confirm it targets the correct TableB rows.
SELECT b.*
FROM TableB AS b
WHERE DCount("*", "TableA", "foreignID =" & b.recordID) = 0;
In human language, that DCount expression means "Give me the count of TableA rows where the foreignID value matches the recordID value of the current TableB row." You want to identify the TableB rows where that count is zero.
Note I assumed numeric data types for both foreignID and recordID. If they are text, you will have to enclose the value of b.recordID in quotes.
When you're ready to pull the trigger, convert to a DELETE query.
DELETE
FROM TableB AS b
WHERE DCount("*", "TableA", "foreignID =" & b.recordID) = 0;

Deleting at most one record for each unique tuple combination

I want to delete at most one record for each unique (columnA, columnB)-tuple in my following delete statement:
DELETE FROM tableA
WHERE columnA IN
(
--some subqueryA
)
AND columnB IN
(
--some subqueryB
)
How is this accomplished? Please only consider those statements that work when used against MSS 2000 (i.e., T-SQL 2000 syntax). I can do it with iterating through a temptable but I want to write it using only sets.
Example:
subqueryA returns 1
subqueryB returns 2,3
If the original table contained
(columnA, columnB, columnC)
5,2,5
1,2,34
1,2,45
1,3,86
Then
1,2,34
1,3,86
should be deleted. Each unique (columnA, columnB)-tuple will appear at most twice in tableA and each time I run my SQL statement I want to delete at most one of these unique combinations - never two.
If there is one record for a given unique (columnA, columnB)-tuple,
delete it.
If there are two records for a given unique (columnA,
columnB)-tuple, delete only one of them.
Delete tabA
from TableA tabA
Where tabA.columnC in (
select max(tabAA.columnC) from TableA tabAA
where tabAA.columnA in (1)
and tabAA.columnB in (2,3)
group by tabAA.columnA,tabAA.columnB
)
How often are you going to be running this that it matters whether you use temp tables or not? Maybe you should consider adding constraints to the table so you only have to do this once...
That said, in all honesty, the best way to do this for SQL Server 2000 is probably to use the #temp table as you're already doing. If you were trying to delete all but one of each dupe, then you could do something like:
insert the distinct rows into a separate table
delete all the rows from the old table
move the distinct rows back into the original table
I've also done things like copy the distinct rows into a new table, drop the old table, and rename the new table.
But this doesn't sound like the goal. Can you show the code you're currently using with the #temp table? I'm trying to envision how you're identifying the rows to keep, and maybe seeing your existing code will trigger something.
EDIT - now with better understood requirements, I can propose the following query. Please test it on a copy of the table first!
DELETE a
FROM dbo.TableA AS a
INNER JOIN
(
SELECT columnA, columnB, columnC = MIN(columnC)
FROM dbo.TableA
WHERE columnA IN
(
-- some subqueryA
SELECT 1
)
AND columnB IN
(
-- some subqueryB
SELECT 2 UNION SELECT 3
)
GROUP BY columnA, columnB
) AS x
ON a.columnA = x.columnA
AND a.columnB = x.columnB
AND a.columnC = x.columnC;
Note that this doesn't confirm that there are exactly one or two rows that match the grouping on columnA and columnB. Also note that if you run this twice it will delete the remaining row that still matches the subquery!

query insert and select explaination

I am confused about this query where it uses insert statement and then ignore and then select. Can someone explain me this? Thanks
INSERT IGNORE INTO
myTable
SELECT
$var1 AS `CMMNCTID`,
$var2 AS `ENCID`,
variableID,
ProductID,
CustomerID,
Age,
"" AS `myJ`,
"" AS `myI`
FROM
table2
JOIN
table3
ON
table2.ID= table3.ID
INSERT IGNORE in a keyword mysql: If the insert will cause a Primary key or Unique key error, it should skip that row.
INSERT ... SELECT: is used to copy data from another table.
http://dev.mysql.com/doc/refman/5.1/en/insert.html
The SELECT is a subquery. What the INSERT is doing is inserting whatever is contained in the join of table2 and table3, into myTable. The IGNORE tells it to ignore any entries for keys that already exist in myTable and to just insert whatever doesn't yet exist.
It seems the purpose of the query is to combine the data that is associated between table2 and table3 and dump it into myTable.
It takes results from the SELECT query on tables table2 and table3 and inserts the results into table myTable. IGNORE keyword simply tells mysql to ignore any errors that occur while executing the INSERT query.

Difference between "IF EXISTS" and "IF NOT EXISTS" in SQL?

I am very new to SQL. I want to know what happens when i use "IF EXISTS" or "IF NOT EXISTS".
For ex: what is the difference between the following two statements:
Statement 1: (EXISTS)
IF EXISTS( SELECT ORDER_ID FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032 )
BEGIN
DELETE FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032
END
Statement 2: (NOT EXISTS)
IF NOT EXISTS( SELECT ORDER_ID FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032 )
BEGIN
DELETE FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032
END
What will the IF EXISTS or IF NOT EXISTS return?
Which is better among these both?
When to use IF EXISTS and when to use IF NOT EXISTS
Here are 4 examples illustrating when you would use IF EXISTS and when you would use IF NOT EXISTS:
A) Delete related records from more than 1 table:
IF EXISTS (SELECT TOP(1) 1 FROM Table1 WHERE ORDER_ID = 11032) BEGIN
DELETE FROM Table1 WHERE ORDER_ID = 11032
DELETE FROM Table2 WHERE ORDER_ID = 11032
-- possibly more statements following here ...
END
B) Update record in more than 1 table if it exists:
IF EXISTS (SELECT TOP(1) 1 FROM Table1 WHERE ORDER_ID = 11032) BEGIN
UPDATE Table1 SET Field1='X' WHERE ORDER_ID = 11032
UPDATE Table2 SET Field2='Y' WHERE ORDER_ID = 11032
-- possibly more statements following here ...
END
C) Insert record in more than 1 table if it does not exist:
IF NOT EXISTS (SELECT TOP(1) 1 FROM Table1 WHERE ORDER_ID = 11032) BEGIN
INSERT INTO Table1(Field1, Field2, ORDER_ID) VALUES ('A', 'B', 11032)
INSERT INTO Table2(Field3, Field4, ORDER_ID) VALUES ('X', 'Y', 11032)
-- possibly more statements following here ...
END
D) Upsert (=insert or update) record, depending on existence:
IF EXISTS (SELECT TOP(1) 1 FROM Table1 WHERE ORDER_ID = 11032) BEGIN
UPDATE Table1 SET Field1='X' WHERE ORDER_ID = 11032
-- possibly more statements following here ...
END
ELSE BEGIN
INSERT INTO Table1(Field1, Field2, ORDER_ID) VALUES ('X', 'B', 11032)
-- possibly more statements following here ...
END
Instead of the above statement (case D), you can also use the new MERGE statement, but I think it's a bit complicated to use.
NOTES:
If there is just one table affected, you would not use EXIST in any of the examples above, except in the upsert example D).
SELECT TOP (1) 1 FROM ... is more efficient, because it aborts after the 1st match is found, then it returns just number 1 (which is more efficient to select for instance a NVARCHAR(max) field)
You can see that only in example C) you are forced to use IF NOT EXISTS(...), all other examples are using IF EXISTS(...) which is more efficient.
You need the first statement. Basically "IF EXISTS" returns true if the query return 1 or more rows, so in you example it will return a single row (containing a field with value 1) so will execute the delete statement as you desire.
Both statements will return a boolean true/false result.
EXISTS returns true if the result set IS NOT empty.
NOT EXISTS Is a negated operation, so it returns true if the result set IS empty
If there are order_details with an order_id equal to 11032, your first statement will run :
DELETE FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032
If there are not order_details with an order_id equal to 11032, then your second statement will run. Note that this is an empty set since you just checked that there were not orders with that order_id.
It's actually going to be easier, in this example, to just run the DELETE - the IF EXISTS and IF NOT EXISTS are superfluous.
IF EXISTS checks that the result set is not empty, and IF NOT EXISTS checks that the result set is empty.
Which is better among these both?
The one that gives you the appropriate semantics.
When to use "IF EXISTS" and when to use "IF NOT EXISTS"
When you need to check the non-emptiness or emptiness of a result set.
"EXISTS simply tests whether the inner query returns any row. If it does, then the outer query proceeds. If not, the outer query does not execute, and the entire SQL statement returns nothing." See here. NOT EXISTS is the negation of EXISTS of course.
What the first statement does is that it will issue a DELETE query if the order can be found. The second one does not have any sense as it will issue the query on the ORDER when it does not exist.
This is certainly one way to use an EXISTS. I'm not sure that the second one would do anything though.
However, you could just
DELETE FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032
and remove the EXISTS altogether, unless you wanted to perform
IF EXISTS ( SELECT ORDER_ID FROM ORDERS WHERE ORDER_ID = 11032 ) BEGIN
DELETE FROM DBO.ORDER_DETAILS WHERE ORDER_ID = 11032
DELETE FROM DBO.ORDERS WHERE ORDER_ID = 11032
END
or your actual code was more complex than what is shown.
Your second statement will never delete anything since, if there are rows, it will evaluate to FALSE and not perform the DELETE and if there are not rows, it will evaluate to TRUE and execute the DELETE which will do nothing since there are no rows.
As far as performance, in the context in which you use the EXISTS neither one has a better performance since it's really just evaluating whether the result set from the SELECT is NULL or not.
There is another use of EXISTS in which NOT EXISTS is much less efficient than EXISTS and can be effectively replaced with a better performing phrase. I'm referring to when you use NOT EXISTS in the WHERE clause of a statment. In this cause you would be better off performing a LEFT JOIN (instead of the INNER JOIN you likely have) and filter WHERE rightTable.SomeColumn IS NULL.