SQL Statement deleting entire table - sql

I have two tables that both have an ID number which are linked together (AllUsers and AllProfiles). When the user presses a button, I want the AllUsers table to check for IDs it has that are not present in the AllProfiles table and delete them. I'm new to SQLCE and hacked this together. The problem is, it keeps deleting the entire table. Why?
DELETE FROM AllUsers
WHERE EXISTS
(SELECT ID
FROM AllUsers
WHERE (ID NOT IN
(SELECT ID
FROM AllProfiles)))
Also, is this an efficient way of bulk deleting thousands of records? I tried Linq's DeleteAllOnSubmit but it was too slow. I'm hoping since the above is comparing two tables directly, it should be efficient.
(I don't want to use cascading as I need control of each table individually)
EDIT - The SELECT statement correctly returns the missing IDs, so there's something wrong with the DELETE FROM AllUsers WHERE EXISTS part.

You're basically saying
delete from allusers
where TRUE -- this is pseudo, but you get the idea
Your original query deletes the whole table because the only condition is boolean... if that returns data then it'll delete all the data. If your exists clause does not return data it would not delete any data.
You want something like this (I'm not fluent with CE, but you should be able to make a minor modification if it doesn't 100% transport over to CE):
delete from allusers
where id not in
(
select id
from allprofiles
)

Related

Using a Delete query on a single table when referencing other tables

I want to run a delete query to remove certain data from a table in a Sharepoint list using an MS Access query. However I want to be sure only to delete from a single list based on the values of another table.
The table is TMainData: This consists solely of number fields that are references to the keyfields in other tables, such as TProgram which has a program name, or TContact which has the point of contact, or TPositionTitle which has a title like Site Director.
So a TMainData entry looks something like
ProgramID, which links to TPrograms: 4
ContactID, which links to TContacts: 42
PositionTitle, which links to TPositionTitle: 3
This tells me that the Site Director (TPositionTitle 3) of Anesthesiology (ProgramID 4) is John Smith (ContactID 42).
Here's where it gets tricky: I have a reference under TPrograms to TProgramType. I want to delete all records under TMainData where they link to a certain Program Type, because that program type is going away. HOWEVER... I don't want to delete the program itself (yet), just the lines referencing that program in TMainData.
The "manual" way I see to do this is to run queries that identify what the ProgramIDs are of the programs I want to delete the contacts for, and then use those IDs in a delete query that only references the TMainData query. I'm wondering if there's a way to use referential data, because I may have to be running some ridiculous update queries at a later time that would need this same info.
I dug through https://support.office.com/en-us/article/Use-queries-to-delete-one-or-more-records-from-a-database-A323BF1A-C9B4-4C86-8719-BE58BDF1B10C but it doesn't seem to cover deleting from one table based on values referenced in another table.
You already seem to understand what you need to do to achieve the desired result when you state:
...run queries that identify what the ProgramIDs are of the programs I want to delete the contacts for, and then use those IDs in a delete query that only references the TMainData query.
If I've understood your description correctly, I would suggest something along the lines of:
delete from tmaindata
where
tmaindata.programid in
(
select tprograms.programid
from tprograms
where tprograms.tprogramtype = 'YourProgramType'
)
Always take a backup of your data before running delete queries - there is no undo.

How to delete a duplicate record without using primary key

I went for an interview today where they give me technical test on sql. One of them was how to delete duplicate records without a primary key.
For one I can't imagine a table without a primary key. Yes I have read the existing threads on this. Say this happened and needed to be fixed Now. Couldn't I just add to the end of the table a automatically incrementing id then use that to delete the duplicate record?
Can anyone think of a reason why that won't work? I tried it on a simple database I created and I can't see any problems
You've got a couple of options here.
If they don't mind you dropping the table you could SELECT DISTINCT * from the table in question and then INSERT this into a new table, DROPping the old table as you go. This obviously won't be usable in a Production database but can be useful for where someone has mucked up a routine that's populating a data warehouse for example.
Alternatively you could effectively create a temporary index by using the row number as per this answer. That answer shows you how to use the built in row_number() function in SQL server but could be replicated in other RDBMS' (not sure which but MySQL certainly) by declaring a variable called #row_num or equivalent and then using it in your SELECT statement as:
SET #row_num=0;
SELECT #row_num:=#row_num+1 AS row_num, [REMAINING COLUMNS GO HERE]
One of possible options how to do this:
select distinct rows from your table(you can achieve this using group by all columns)
insert result into new table
drop first table
alter second table to name of first one
But this is not always possible in production

How to create query to update records only when changes occur and to add new records that do not already exist

I am running a query that fetches data(records) form a linked table from another database.
The linked table is populated by users using a form remotely, like the web.
I created this piece of code that queries the data from the linked table into a new table, like this:
`INSERT INTO NEW_TBL(ENT_CUS_NUM, ENT_FIRST_NAME, ENT_LAST_NAME, ENT_ADDRESS1, ENT_CITY, ENT_STATE, ENT_ZIP, ENT_PHONE)
SELECT LINK_TBL.CUS_NUM, LINK_TBL.FIRST_NAME, LINK_TBL.LAST_NAME, LINK_TBL.ADDRESS1, LINK_TBL.CITY, LINK_TBL.STATE, LINK_TBL.ZIP, LINK_TBL.PHONE
FROM LINK_TBL`
Is it possible to modify this query so that it inserts new records from the link table if the record has not already been added, or update existent records
that have been modified? Example: Lets say a person changes their address, Can I update or bring over only their address without re-inserting their entire record because of an address change?
This is what confuses, I could write an update statement but modifying this querying so that it brings over new records or update records with changes is way over my head.
I would appreciate your input and help.
Guy
If you can designate a field as a unique key, you can use REPLACE INTO instead of INSERT INTO at least with mysql

Can you tell SQL Server not to return specific rows?

We have a database where contacts are only soft-deleted, i.e. we set a bit named deleted to true. The API handles this, but sometimes you need to run queries directly against the database and it's easy to forget that bit, and export contacts that are actually deleted. It's not a big problem, because I'm used to the system, but if I'm on holiday, or if someone else is to take over I'd like to make sure these rows are not returned - unless specifically asked for. This leaves us with the following two questions:
Is there a way to tell SQL Server (2005 in this case) not to return rows if for example a bit is set to true?
If so, can these rows still be retrieved if specifically asked for (where bit = 'true')?
In order to select either the non-deleted rows or the deleted ones, create two views:
CREATE VIEW ActiveContacts
AS
SELECT (list of fields)
FROM dbo.Contacts
WHERE deleted = 0
CREATE VIEW DeletedContacts
AS
SELECT (list of fields)
FROM dbo.Contacts
WHERE deleted = 1
Now, you can easily just pick from either the active or the deleted contacts:
SELECT (list of fields)
FROM ActiveContacts
SELECT (list of fields)
FROM DeletedContacts
That way, you can easily encapsulate that selection criteria and if you don't return that "deleted" flag in your view, outside users won't even see that flag and won't know it's there.
Marc
The only way that I can see to automatically do this for you would be to create views on the relevant tables that specifically exclude the deleted rows. Then use the real tables when you need to see the deleted data.
You could create a view that hides those rows, and if you need the rows directly, you can still go to the table. Try CREATE VIEW vwBlah AS SELECT table, columns, go, here FROM TableName WHERE flag = 0.

How do I know if record from an SQL database is being used elsewhere?

Is there a way to know that a record is being used by another record in the database?
Using deleting as an example: When I create an SQL statement trying to delete a group in dbo.group I get this error:
The DELETE statement conflicted with the REFERENCE constraint "FK_MyTable". The conflict occurred in database "MyDB", table "dbo.User", column 'Group_ID'.
Since I have a user that has a foreign key relationship to the group I am not able to delete the group. I want to be able to know if the record is linked to other records before I run the delete statement. Is there a way to do that?
Basically I want to show the user that the record that they are viewing is undeleable. I do not want to try to delete the record.
Other folks are suggesting ways to detect dependent rows, but the problem with this is that there's a race condition: if your test finds no dependent rows, and you try to delete the group, there might be another client application that adds a dependent row in the brief moment between your two queries. So your information that the group is unused is potentially outdated as soon as you get it.
The better approach is to try to delete the group, and handle any errors that are raised.
This is also better for performance, because you don't have to run any SELECT query to check if the dependent rows exist.
Re your comment and edited question: Okay, fair enough, it makes sense to use this information to give hints to the user (e.g. display a "delete group" button or else gray out the button).
In that case, you can use one of the suggestions from other folks, such as query the count of dependent rows in the Users table. If you need information for multiple groups, I'd do one query, joining Groups to Users and then group by the group id.
SELECT g.groupid, COUNT(*) AS user_count
FROM dbo.Groups g JOIN dbo.Users u ON (g.groupid = u.groupid)
GROUP BY g.groupid;
That'd be better than running a separate SQL query for each group to get the count of users.
If you don't know how many tables may depend on Groups, you should learn to use the INFORMATION_SCHEMA system views to query for metadata. I don't think this is the case for you, so I won't go into detail.
Do a query which checks if there are users which have the column group_id set to the id you want to delete. If the query returns 0 rows you can delete without exception
SELECT count(group_id)
FROM dbo.User
WHERE group_id = [yourgroupidtodeletevalue]
You can set up cascading deletes.
You can query the Forign Key table. The error tells you which table is dependent on the foreign key lookup.