Question

I would appreciate some help with an SQL statement I really can't get my head around.

What I want to do is fairly simple, I need to take the values from two different tables and copy them into an master table when a new row is inserted into one of the two tables.

The problem is perhaps best explained like this:

I have three tables, productcategories, regioncategories and mastertable.

         ---------------------------
TABLE:   PRODUCTCATEGORIES
         ---------------------------
COLUMNS: CODE       | DESCRIPTION
         ---------------------------
VALUES:  BOOKS      | Books
         ---------------------------

         ---------------------------
TABLE:   REGIONCATEGORIES
         ---------------------------
COLUMNS: CODE       | DESCRIPTION
         ---------------------------
VALUES:  EU         | European Union
         ---------------------------

         ------------------------------------------
TABLE:   MASTERTABLE
         ------------------------------------------
COLUMNS: REGION     | PRODUCT       | ACCOUNT
         ------------------------------------------
VALUES:  EU         | BOOKS         | NULL
         ------------------------------------------

I want the values to be inserted like this when a new row is created in either productcategories or regioncategories.

New row is created.

         ---------------------------
TABLE:   PRODUCTCATEGORIES
         ---------------------------
COLUMNS: CODE       | DESCRIPTION
         ---------------------------
VALUES:  BOOKS      | Books
         ---------------------------
VALUES:  DVD        | DVDs
         ---------------------------

And a SQL statement copies the new values into the mastertable.

         ------------------------------------------
TABLE:   MASTERTABLE
         ------------------------------------------
COLUMNS: REGION     | PRODUCT      | ACCOUNT
         ------------------------------------------
VALUES:  EU         | BOOKS        | NULL
         ------------------------------------------
VALUES:  EU         | DVD          | NULL
         ------------------------------------------

The same goes if a row is created in the regioncategories.

New row.

         ---------------------------
TABLE:   REGIONCATEGORIES
         ---------------------------
COLUMNS: CODE       | DESCRIPTION
         ---------------------------
VALUES:  EU         | European Union
         ---------------------------
VALUES:  US         | United States
         ---------------------------

Copied to the mastertable.

         ------------------------------------------
TABLE:   MASTERTABLE
         ------------------------------------------
COLUMNS: REGION     | PRODUCT       | ACCOUNT
         ------------------------------------------
VALUES:  EU         | BOOKS         | NULL
         ------------------------------------------
VALUES:  EU         | DVD           | NULL
         ------------------------------------------
VALUES:  US         | BOOKS         | NULL
         ------------------------------------------
VALUES:  US         | DVD           | NULL
         ------------------------------------------

I hope it makes sense.

Thanks,

Stefan

Was it helpful?

Solution 4

Alright, thank you for your answers and suggestions.

I am working with an access project connected to MsSQL database. I tried to solve this by using a table trigger, but none of the suggestions has done the trick for me. Therefore I decided to solve this on the client side with VBA code instead.

It is probably not the proper way to solve it, but it might be useful to know for anyone reading.

The table structure is the same, but I have made a corresponding form for both the product and region table. On the forms AfterInsert event I have the following code:

Region table:

Private Sub Form_AfterInsert()

Dim varRegion As String
Dim strSQL As String

varRegion = Me![code]
strSQL = "INSERT INTO master([region], [product]) SELECT '" & varRegion & "', & _
          [code] FROM product;"

    DoCmd.RunSQL strSQL

End Sub

Product table:

Private Sub Form_AfterInsert()

Dim varProduct As String
Dim strSQL As String

varProduct = Me![code]
strSQL = "INSERT INTO master([region], [product]) SELECT [code], & _ 
          '" & varProduct & "' FROM region;"

    DoCmd.RunSQL strSQL

End Sub

EDIT: Having research the matter a little bit more, I found that this is the code you need to be using for the trigger if you are using SQL Server, if you don't want to use the client side setup.

Apparently, in SQL Server you need to reference a hidden table called "inserted" when you want to get the values of the inserted row. View this link for more info: Multirow Considerations for DML Triggers

Great!

Product table:

-- Trigger statement
CREATE TRIGGER "name-of-trigger"
ON producttable
FOR INSERT AS

    -- Insert statement
INSERT INTO mastertable ([region],[product])
SELECT regiontable.[code], inserted.[code]
FROM regiontable, inserted;

Region table:

-- Trigger statement
CREATE TRIGGER "name-of-trigger"
ON regiontable
FOR INSERT AS

    -- Insert statement
INSERT INTO mastertable ([product],[region])
SELECT producttable.[code], inserted.[code]
FROM producttable, inserted;

OTHER TIPS

You can easily build your "master table" in runtime:

SELECT  *
FROM    regiontable
CROSS JOIN
        producttable

It will be more efficient, since, unlike the materialized master table, both tables will probably fit into the cache.

If for some reason you'll need to have it materialized, then just write the triggers on both tables:

INSERT
INTO    mastertable
SELECT  r.code, NEW.code
FROM    regiontable t

on mastertable, and

INSERT
INTO    mastertable
SELECT  NEW.code, p.code
FROM    producttable p

on producttable.

There are two ways of inserting the extra information into the MASTERTABLE.

  1. Use triggers - when an insert occurs in PRODUCTCATEGORIES or REGIONCATEGORIES, an insert trigger fires and checks if the row exists in the MASTERTABLE. If not it is added.

  2. Create a stored procedure to insert data into the PRODUCTCATEGORIES and REGIONCATEGORIES table. The stored procedure is then responsible for checking the MASTERTABLE and inserting if necessary.

The 2nd approach has the advantage that it's obvious to someone else maintaining your code what's going on. Triggers can hide important functionality. Stored procedure are usually preferred for transact SQL for performance reasons.

Your master table appears to be a cross join of all potential combinations. Thus when you add a new region, you are having to add all potential products in that region. This is a lot of effort for data which can simply be inferred from all potential regions and all potential categories.

I know you mention that there are additional columns. What do these additional columns contain?

I would typically not keep such a table materialized on a normalized database - unless the additional columns you are alluding to need to be assigned in some special way at creation and then altered in some kind of maintenance - even in that case, a sparse table (i.e. only departures from the defaults) with appropriate defaults can work well.

I do have a similar cross join in one of my systems and it contains about 25m rows and allows us to replace very complex logic over a 2-Dimensional 2500 general ledger accounts x 10000 cost centers space where there are "rows" and "columns" of identical logic, yet "islands" of logic.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top