how does an update work? is it a transaction? - sql-server-2008

I have this table:
Mytable(ID, IDGroupReference, Model ...)
I have many records in MyTable. The belong to a group, so all the records that belong to the same group has the the same IDGroupReference. IDGroup reference is the ID of one of the records that belong to the group. So all the records of a group has the same IDGroupReference, I can get all the records of the group with a single query:
select * from MyTable where IDGroupReference = 12345;
I can change one record from one group to another, in this case I want to change also all the records of the group too. I mean, I want to merge two groups in one.
In this case I can use this query:
Update Mytable set IDGroupReferencia = myIDReferenceGroup1 where IDGroupReference = IDGroupReferencieGroup2
I set the IDGroupReference of the group 2 with the IDGroupReference of the group one.
My doubt is about the concurrency, when two users try to change the group of two different records. Imagine the I have the group 1 with 10.000 records and tow users. User 1 try to change the record A of the group 1 to group 2 and user 2 try to change the record B from group 1 to group 3.
How the group has many records, 10.000, I think that when I try to update IDGroupReference with the query that I describe above, SQL Server update one by one, and how there are many records, it's is possible that some records are in the group b and other records go are in the group 3, when all of the must be in the same group, in the group 2 or 3, depends of which user is the last to update. But all of the records must be in the same group, not split.
So, when I use the update, how does it work? is a transaction and nobody can update any of the records that will be affected or a second user can update records in the middle of the update of the first user?
I mean:
group 1 with 10 records. User one execute the update. So the steps are:
SQL Server updates record 1.
SQL Server updates record 2
Meanwhile, a second user execute the query.
it is possible that the second user update the record 3 before is update by the query of the first user? Because if this happends, then the group 1 is splitted in two groups, some records go to group 2 and some of them go to group 3.
How can I ensure that all the records of the group 1 go to group 2 or group 3?
Thanks.

The solution is to use the hints of SQL Server. In this link there are more information.
The initial update:
Update Mytable set IDGroupReferencia = myIDReferenceGroup1 where IDGroupReference = IDGroupReferencieGroup2
It ss modify to:
Update Mytable with(tablock) set IDGroupReferencia = myIDReferenceGroup1 where IDGroupReference = IDGroupReferencieGroup2
By default SQL Server, with the update, only block the record that is being updated, but the rest can be modified. So I need to block all the table, to avoid that other update modify records in the middle of other update process.
The use of "with(tablock)" makes that, block the table when an update begins. then search for all the records that match with the where and update it. When the table is block, no other user can select or update records from this table. that is what I need in my particular case.

Related

Delete query using COUNT and MIN. MS Access 2010

I am trying to identify and remove duplicates from a data extract.
I have setup a query to group by contract_number and count > 1 which identifies the cases and there are two contract_start_date's of which I need to remove the earliest so I have applied min.
I am unable to run this as delete query. I am fairly new to Access and SQL Scripts.
SELECT Gas_Data.CONTRACT_NUMBER,
Count(Gas_Data.CONTRACT_NUMBER) AS CountOfCONTRACT_NUMBER,
Min(Gas_Data.CONTRACT_START_DATE) AS MinOfCONTRACT_START_DATE
FROM Gas_Data
GROUP BY Gas_Data.CONTRACT_NUMBER
HAVING (((Count(Gas_Data.CONTRACT_NUMBER))>1));
Try this approach where you, in the subquery, identify those records not to be deleted:
DELETE
*
FROM
Gas_Data
WHERE
Gas_Data.CONTRACT_START_DATE Not IN
(SELECT
Max(T.CONTRACT_START_DATE)
FROM
Gas_Data As T
WHERE
T.CONTRACT_NUMBER = Gas_Data.CONTRACT_NUMBER)
Of course, do make a backup first.
Consider the following:
delete from gas_data a
where exists
(
select top 1 * from gas_data b
where
a.contract_number = b.contract_number and
a.contract_start_date < b.contract_start_date
)
For every record, the above will test whether there is at least one other record in the dataset for which the contract number is equal and the start date is later. If such a record exists, the earlier record is deleted.
Always retain a backup of your data before running delete queries.
Try:
DELETE FROM Gas_Data
WHERE Count(Gas_Data.CONTRACT_NUMBER)>1

Delete Query deletes all records without leaving the original ones when duplicates are detected

I have two tables, tbl_NTE and tbl_PAH. There are records in tbl_PAH that is already available in tbl_NTE that is why I created an append query to automatically transfer and update some records which as a result causes duplicates every time I click the save button because the save button triggers the append query query.
I want to run a query where all the data with duplicates are deleted and just leave the original ones.
I created a delete query and typed the criteria:-
In (SELECT [CaseIDNo]
FROM [tbl_PAH] As Tmp GROUP BY [CaseIDNo]
HAVING Count(*)>1 )
I've also tried Last, First, Max and Group By as criteria but all it does it delete all the records as well.
In (SELECT DISTINCTROW tbl_PAH.CaseIDNo
FROM tbl_PAH
GROUP BY tbl_PAH.CaseIDNo
HAVING (((tbl_PAH.CaseIDNo) In (SELECT Last(tbl_PAH.CaseIDNo) AS
LastOfCaseIDNo FROM tbl_PAH Group By tbl_PAH.CaseIDNo HAVING
(((Count(tbl_PAH.CaseIDNo))>1));)));)
Here is the other one I've tried but also deletes the whole records of duplicates without leaving the original one.
DELETE tbl_PAH.CaseIDNo
FROM tbl_PAH
WHERE (((tbl_PAH.CaseIDNo) In (SELECT DISTINCTROW tbl_PAH.CaseIDNo
FROM tbl_PAH
GROUP BY tbl_PAH.CaseIDNo;)));
and when I run it, all the duplicates are deleted without leaving the original ones. Any idea on how I can work this out?
I've already set the Unique Records to Yes. I set the index to Yes (Duplicates Ok) to have no error while automatically appending the records to other tables but as a result, duplicates are created. Any help on deleting the duplicates with the criteria "When a record has duplicates in terms of CaseIDNo, the duplicates will be deleted leaving only the original record." I am a newbie at MS Access 2010 that is why I am still learning. I am using Microsoft Access 2010. Thank you in advance to those who will answer.
You can use the following query to delete all duplicate records where ID is not the minimal value of ID. Since ID is a unique column, that should leave the originals in place.
Note that I've refactored your first condition from an IN to an EXISTS, because those are often faster and more reliable.
DELETE tbl_PAH.CaseIDNo
FROM tbl_PAH t
WHERE EXISTS (SELECT 1 FROM tbl_PAH s WHERE s.CaseIDNo = t.CaseIDNo HAVING COUNT(s.CaseIDNo) > 1)
AND t.ID <> (SELECT Min(s2.ID) FROM tbl_PAH s2 WHERE t.CaseIDNo = s2.CaseIDNo)

How to find and remove duplicate records from multiple column,keep only one full record

I am trying to find duplicates from a table based on multiple columns. I have a table which has a columns like Email(Office),Email(Personal1) & Email_Personal2, Mobile_Personal1, Mobile_Personal2, FirstName,MiddleName,LastName,CompanyName,Designation etc. It has millions of records. There are so many duplicates for a specific record.
The folowing image represents the sample Table:
Now, I want to find the record using sql query which has the full values in its columns, want to keep this record and delete remaining all.
select *,count(*) from mytable where first_name!="" group by First_Name,Email_Office,Email_Personal1,Email_Personal2,Personal_Mobile1,Personal_Mobile2 having count(*)>1
But its showing me a specific record with total number of occurrence in last count(*) column only. Guide me in above query how can I see a record which has all the details along with number of occurrences of that specific record? How do I keep that one complete record and delete remaining all from a table?
I've removed "having count(*) >1" to see each record from above query but its taking so much time to show the output,almost feel like its getting hanged.
select t.* from mytable t inner join (select first_name,middle_name,last_name,designation,company_name,email_office,email_personal1,email_personal2,personal_mobile1,personal_mobile2,count(*) as NoDuplicates from mytable group by first_name,middle_name,last_name,designation,company_name,email_office,email_personal1,email_personal2,personal_mobile1,personal_mobile2 having NoDuplicates > 1) tsum on t.first_name=tsum.first_name and t.Middle_Name=tsum.middle_name and t.Last_Name=tsum.last_name and t.Designation=tsum.designation and t.Company_Name=tsum.company_name and t.Email_Office=tsum.email_office and t.Email_Personal1=tsum.email_personal1 and t.Email_Personal2=tsum.email_personal2 and t.Personal_Mobile1=tsum.personal_mobile1 and t.Personal_Mobile2=tsum.personal_mobile2

How to run a Query in Access for a 30,000 records in a table of 800,000 records?

How to run a Query in Access for the first 30,000 records in a table of 800,000 records?
UPDATE Table1 SET TIME = TimeSerial(Left(TIME,2),Right(TIME,2),0);
Ok the first thing to remember is that records could be pulled in any order, so we probably want to ORDER BY, to ensure that the top 30,000 records are the same each time (or if you want the next 30,000 records, that you don't end up repeating yourself etc.) I assumed you have some sort of id, you can figure out what to order by yourself.
What you're looking for is
UPDATE (SELECT TOP 30000 * FROM Table1 ORDER BY Table1.id) AS a
SET a.TIME = TimeSerial(Left(a.TIME,2),Right(a.TIME,2),0);

Set sequential number in mysql table only where rows have same value

I have a table in which a new entree gets a number 0, and a status of unpublished. Users can publish or unpublish rows. When they do, the published row should get a number that's consecutive, but the unpublished rows should be skipped. Like this:
status | number
=============================
unpublished | 0
published | 1
unpublished | 0
unpublished | 0
published | 2
published | 3
unpublished | 0
published | 4
Right now I use:
mysql_query("update albums
join (SELECT #i:=0) t
SET id =(#i:=#i+1)");
When a user publishes something, but that will add consecutive number to all rows.
I need something like the above, but with some sort of WHERE = published statement in it, but I don;t know how.
What solution should I look into?
Many thanks,
Sam
Try an IF in the UPDATE statement:-
UPDATE albums
JOIN (SELECT #i:=0) t
SET id = IF(status='published', #i:=#i+1, 0)
However this is not going to consistently work as I think you want I suspect without an ORDER BY clause (update does support and order clause).
EDIT - further info as requested:-
Albums is a MySQL table. The UPDATE query in MySQL does support the ORDER BY clause (to update records in a particular order), but only for queries where there is only a single table. In this query a sub query is joined to the albums table (ie, JOIN (SELECT #i:=0) t ); even though this is not actually a table it seems MySQL regards it as one and so will not allow an ORDER BY clause in this update.
However #i is a user defined variable and can be initialised by a separate SQL statement. If your query was 2 statements:-
SET #i:=0
UPDATE albums
SET id = IF(status='published', #i:=#i+1, 0)
ORDER BY albums.insert_date;
then that should do it (note, I have just assumed a random column name of insert_date to order the records by).
However many MySQL api's do not support multiple statements in a single query. As #i is a user variable it is related to the connection to the database. As such if you issue one query to initialise it and then a 2nd query (using the same connection) to process the UPDATE it should work.
If you are using php with MySQLi then you can use mysqli-multi-query to perform both in one go.
Kickstarts answer is almost what I need, only if an entree gets published it should always be gets the highest number. Right now it follows the database order, which is by date. Should I integrate an ORDER BY, or is there a different solution?
Thanks