views:

77

answers:

3

I am trying to update my current table by drawing data from another table. My database (dbo_finance) column - test

The other database is assestsc and I am going to pull the data from column issuename1, however I only want to pull the issuename1 when the field [MinSecClass] is = 9. This is what I wrote

UPDATE dbo_finance 
SET [dbo_finance].cusip9 = AssetsC.cusip
FROM dbo_finance INNER JOIN AssetsC ON dbo_finance.test = AssetsC.[IssueName1]
WHERE (AssetsC.MinSecClass = 9)

Thanks, first time really using SQL

+2  A: 

Well I would use aliases, it's a good habit to get into:

UPDATE f
SET [dbo_finance].cusip9 = AssetsC.cusip 
FROM dbo_finance f 
INNER JOIN AssetsC a ON f.test = a.[IssueName1] 
WHERE (a.MinSecClass = 9) 

Now that will work fine if the assets table will only return one value for cuspid for each record. If this is a one to many relationship you may need to get more complex to truly get the answer you want.

I see several serious design flaws in your table structure. First joins fields that are dependant as something as inherently unstable as issue name are a very poor choice. You want PK and FK field to be unchanging. Use surrogate keys instead and a unique index.

The fact that you have a field called cusp9 indicates to me that you are denormalizing the data. Do you really need to do this? Do you undestand that this update will have to run in a trigger ever time the cuspid assoicated with MinSecClass changes? Whya re you denormalizing? Do you currently have performance problems? A denormalized table like this can be much more difficult to query when you need data from several of these numbered fields. Since you already have the data in the assets table what are you gaining except a maintenance nightmare by duplicating it?

HLGEM
"I would use aliases, it's a good habit to get into" -- For the table being updated by the `UPDATE` statement, I would strongly disagree. The sytax you posted violates Standard SQL and for good reason. Think about it: the table expression with the correlation name acts as a materialized table and the UPDATE would be applied to the materialized table and not the underlying base table i.e. the UPDATE would have no effect. The Standard SQL approach has the advantages of being logical (as regards materialized tables), portable and predictable (because scalar subquires are enforced.
onedaywhen
...it's just a shame about the repeated subquery (e.g. from a maintenance point of view) but the hope is that the optimizer realises they are the same.
onedaywhen
"The fact that you have a field called cusp9" -- good spot! I agree this smells.
onedaywhen
Well portability is overrated, very few business databases need portability. In SQL Server this works and it does in fact update the table. It is often a bad practice from a performance standpoint to use a subquery where a join will do. Performance is database specific which is why writing standard SQL is usually a poor idea. Use what the database is designed to use for performance not some standard SQl in case we might someday need to change backends. This is why most COTS software works so badly, it uses standard sql techniques instead of what is optimzed for the backend actually being used.
HLGEM
Your above points are valid, though opinionated. I find `UPDATE f` to be illogical and harder to read i.e. the intention is not to update the materialized table `f` but rather the base table `dbo_finance` for which I have to examine the `JOIN` clauses. No big deal, though.
onedaywhen
"It is often a bad practice from a performance standpoint to use a subquery where a join will do" -- note Standard SQLy requires a *scalar* subquery whereas the SQL Server proprietary `JOIN` can return multiple values from which one is arbitrarily and silently picked. I'd happily settle for poor performance over the wrong result any day ;)
onedaywhen
+1  A: 
UPDATE dbo_finance
   SET cusip9 = (
                 SELECT A1.cusip
                   FROM AssetsC AS A1 
                  WHERE dbo_finance.test = A1.IssueName1
                        AND AssetsC.MinSecClass = 9
                )
 WHERE EXISTS (
               SELECT *
                 FROM AssetsC AS A1 
                WHERE dbo_finance.test = A1.IssueName1
                      AND A1.MinSecClass = 9
              );
onedaywhen
A: 

Because you're using SQL 2008, you can take advantage of the new(ish) MERGE statement.

MERGE INTO dbo_finance
USING (SELECT IssueName1, cusip FROM AssetsC WHERE MinSecClass = 9) AS source 
ON dbo_finance.test = source.IssueName1
WHEN MATCHED THEN UPDATE SET dbo_finance.cusip9 = source.cusip;
hwiechers
Appreciated everyone, i got the answers i was looking for, and also thanks for showing me this MERGE statement, got me into the next step i was looking into, thanks!
quickswitch
Please mark this as the answer so that I can get some points.
hwiechers