-2

Here Is a photo description Of My Example and down the Photo is My Question

The Challenge is that, when I change the name of One of My Retail Shop I want for the Sales Table:

RetailName to stay the Deleted name (I mean the Changed Name) for records with previous months Sales Date and RetailName to be the New Inserted Name for Records from this Month Onward. The reason for doing this is that when I will be searching Sales Table in the future I will be doing so by the Name of the Retail at that time not the new name and also for some other reasons.

I thought of Using an INSTEAD OF UPDATE trigger on table MyRetails to Duplicate the Record and change RetailName value on the duplicated record to the New RetailName instead of Updating when a user tries to Update it then using the same trigger to Loop through Sales table so as to change the foreign Key RetailName to the newly created One for those records whose Sale Date = This Month, But unfortunately I was Unable to write the T-SQL for that . . . Also to relate the 2 Names for the One Retail and not to be confused as two Retail Shops I thought of adding a field which will contain values that will categorize the 2 Records together.

Can Somebody help to tackle this problem?

NB: Don't wonder why I Used RetailName As PK instead of RetailID, it was meant to be like that for some reasons.

Thom A
  • 88,727
  • 11
  • 45
  • 75
Meshka
  • 1
  • 2
  • "Don't wonder why I Used RetailName As PK instead of RetailID, it was meant to be like that for some reasons." - erm..... – Mitch Wheat Jul 04 '22 at 08:04
  • 1
    "Has to be" isn't a good reason. Considering that using names as a Primary Key is often a very poor choice for a key candidate, then "has to" isn't a good reason. A Primary Key should be a static value, never changing. The fact that you need the value to change means that it is **not** a good PK candidate; you might have a "has to be the primary key" requirement, but design requirements effectively say it "must not be the primary key candidate". – Thom A Jul 04 '22 at 08:14
  • Arguably this is all unnecessary anyway. There is no real relationship between each of these tables and `MyRetails`, each one should just have their own `RetailName` and `Description`, there is no need for the extra table and foreign key. – Charlieface Jul 04 '22 at 08:30
  • [dup on MS Q&A](https://learn.microsoft.com/en-us/answers/questions/912274/can-i-do-a-partial-cascade-update-on-a-foreign-key.html) – SMor Jul 04 '22 at 11:44

1 Answers1

0

I will provide an answer for you, but let me first clarify:

The reasons you have chosen RetailName instead of some ID are wrong, and you probably will pay dearly in the future for that choice.

But people need to learn the hard way sometimes, so here goes:

Your thoughts (apart from the earlier points) are sound. No need for an instead-of trigger, though; an AFTER trigger will work fine. Adding a field to connect them seems sound, let's call them [MyRetailsGroup] and populate it:

alter table [MyRetails] add [MyRetailsGroup] nvarchar(100) -- or whatever datatype [RetailName] is
update MyRetails set [MyRetailsGroup]=[MyRetails]

The trigger sould look something like this:

create or alter trigger TR_MyRetails_update_PK on [MyRetails]
after update as
begin
    if update([RetailName]) -- only run for primary key change
    begin
    
        -- create new rows for previous PK
        insert [MyRetails]([RetailName],[Description],[MyRetailsGroup])
            select 
                d.[RetailName],d.[Description],d.[MyRetailsGroup]
            from deleted d
                
        -- save previous and next PK to temp table
        select d.[RetailName] as [original],i.[RetailName] as [new]
        into #mr
        from
            inserted i
            inner join deleted d on i.[RetailName]=d.[RetailName]
            
        -- now do your business stuff with those pairs
        update sales set [RetailName]=mr.[new]
        from
            [Sales] sales
            inner join #mr mr on mr.[original]=sales.[RetailName]
        where sales.[Date] >= DATEADD(mm, DATEDIFF(mm, 0, getdate()), 0) -- this month onward
        
        ......
    end
end
George Menoutis
  • 6,894
  • 3
  • 19
  • 43
  • OK Lets Say I choosed RetailID As my PK, in My Frontend's Form for Example MS Access, what will be the the RetailsName shop in January's Sales when I changed the name in March? – Meshka Jul 04 '22 at 09:43
  • Two ideas: 1) You only keep RetailID as PK, and since you care about name historically, you make a new table with RetailID,name,date period, and you can get the name from there with the appropriate join. or 2) You have both RetailID as PK but also RetailName on [Sales], on which you store the RetailName of the time you want. This means that you have a trigger that looks a bit like the one above, but at least you don't have the weird [MyRetailsGroup] column since the ID correctly connects them, and you still keep the FK. – George Menoutis Jul 04 '22 at 10:01
  • Table MyRetails conflicted with all the relationship, then I decided to delete all my relations to table MyRetails, After doing so It duplicates the PK very Nicely but doesn't work on table Sales, Whats wrong? – Meshka Jul 04 '22 at 11:32