| Author |
Topic |
|
Billkamm
Posting Yak Master
124 Posts |
Posted - 2006-01-25 : 08:30:35
|
| I have several scenarios would I have a large group of data (such as customer demograhpics). These demopgraphics are not in a dataset. Each field is individual and I want to be able to take all the information and if it is a change to UPDATE the demographics table and if it is a new demographic not already in the table for that customer to do an INSERT INTO.Does anyone have any suggestions on how to do this? |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
Posted - 2006-01-25 : 08:42:24
|
| One approach isUpdate queryIf @@RowCount=0Insert QueryMadhivananFailing to plan is Planning to fail |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2006-01-25 : 08:47:03
|
| Are ... the missing UPSERT command that is sorely needed in SQL!!Kristen |
 |
|
|
Billkamm
Posting Yak Master
124 Posts |
Posted - 2006-01-25 : 08:52:41
|
| My problem is that the fields I am passing to the procedure are dynamic.One time I can have 5 records I need UDPATEd for the same ID and 4 records that need INSERTed for that same ID. And another time I might have 3 for UPDATE and 14 for INSERT.I could always loop through one record at a time, but that would probably be a huge performance hit and I'm trying to find an easier/better way. |
 |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
Posted - 2006-01-25 : 08:55:58
|
| >>Are ... the missing UPSERT command that is sorely needed in SQL!!Kristen, Which RDBMS supports UPSERT?MadhivananFailing to plan is Planning to fail |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2006-01-25 : 08:57:54
|
Madhi, you're taking things too seriously. It was a joke ... |
 |
|
|
ditch
Master Smack Fu Yak Hacker
1466 Posts |
Posted - 2006-01-25 : 08:58:53
|
Well looks like you have to do it in 2 seperate commands then - one to update existing records and the other to insert new rows.Duane. |
 |
|
|
madhivanan
Premature Yak Congratulator
22864 Posts |
Posted - 2006-01-25 : 09:02:03
|
quote: Originally posted by Kristen Madhi, you're taking things too seriously. It was a joke ... 
MadhivananFailing to plan is Planning to fail |
 |
|
|
Billkamm
Posting Yak Master
124 Posts |
Posted - 2006-01-25 : 09:03:33
|
| ditch,I realize that. What I was planning on doing was inserting all the data into a temporary table and then determining which rows needed UPDATEd and which need INSERTed, but I'm not sure if there is a way to do this with out looping one row at a time.Is there a query or sequence of queries I can use to compare the temporary table to the live table and then UPDATE or INSERT the rows as needed? |
 |
|
|
ditch
Master Smack Fu Yak Hacker
1466 Posts |
Posted - 2006-01-25 : 09:13:31
|
You should possibly look at doing it without temp tables.ie to insert rows that dont exist in the table you can do something like this.insert into existing_tableselect a.*from newdata_table awhere not exists (select b.* from existing_table where a.id = b.id)Duane. |
 |
|
|
Billkamm
Posting Yak Master
124 Posts |
Posted - 2006-01-25 : 09:18:15
|
| I don't see the advantage to creating a permanent table when I just need the data temporarily? |
 |
|
|
ditch
Master Smack Fu Yak Hacker
1466 Posts |
Posted - 2006-01-25 : 09:21:23
|
no - I'm not saying a permanent table is needed - I am assuming that you have data in one table (newdata_table) which is used to update or insert into your main table (existing_table) or am I missing something?Duane. |
 |
|
|
mwjdavidson
Aged Yak Warrior
735 Posts |
Posted - 2006-01-25 : 09:40:37
|
As ever, it would be useful to post some DDL for both your destination and source table(s) (if appropriate) as it's not entirely clear what's going on. It sounds as though you're receiving a number of different feeds (one per field?) each of which associates a customer with a particular piece of demographic information. Am I right in thinking your source is not an RDBMS (quote: These demopgraphics are not in a dataset
)? Or am I completely wide of the mark here!?Mark |
 |
|
|
Billkamm
Posting Yak Master
124 Posts |
Posted - 2006-01-25 : 09:51:32
|
| You are correct. The data source is a web form. I was planning on looping all the textboxes and comboboxes from the web form and creating an SQL statement to insert the values into a temporary table. Then using that temporary table to update or insert new rows into the permanent table. |
 |
|
|
Billkamm
Posting Yak Master
124 Posts |
Posted - 2006-01-25 : 12:51:55
|
| Here is a code listing of what I am trying to do with the UPDATE half of the problem. If you notice towards the bottom I created a check to update and add to the usage log. It seems silly that I would now have to repeat that large block of code for every demographichttp://www.PasteHere.com/?rbsmklIn the near future I will need create a similiar stored procedure that will also allow me to INSERT fields that don't exist. This current example is all UPDATE. |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2006-01-25 : 15:45:55
|
| If you put the data into a temporary table can't you just JOIN it to the main table in two statements:1) Where PK columns match then do an UPDATE2) Where PK column does not exist in Master Table (i.e. needs OUTER JOIN) do an INSERT?Kristen |
 |
|
|
Billkamm
Posting Yak Master
124 Posts |
Posted - 2006-01-25 : 15:55:33
|
| I have to compare the values of waht is in the primary table with what is in the temporary table.I am only updating them if they are different. I do this because I only wish to place in my usage log table entries that have changed. |
 |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2006-01-25 : 16:39:55
|
quote: Originally posted by Billkamm Here is a code listing of what I am trying to do with the UPDATE half of the problem. If you notice towards the bottom I created a check to update and add to the usage log. It seems silly that I would now have to repeat that large block of code for every demographichttp://www.PasteHere.com/?rbsmklIn the near future I will need create a similiar stored procedure that will also allow me to INSERT fields that don't exist. This current example is all UPDATE.
If you want us to look at code, it's better to just paste it here into a code block to make it readable.I usually will not click on a link like that. I don't know about other people, but I doubt if I'm the only one that feels that way.CODO ERGO SUM |
 |
|
|
Billkamm
Posting Yak Master
124 Posts |
Posted - 2006-01-25 : 16:48:17
|
I normally do paste the code in here, but it was large amount of code, so I did that link instead.Here is the updated code. The problem I ran into here is that the EXEC() statement is trying to access out of scope varaiables and I don't want to have to pass every parameter each iteration through the loop-- Will update all the demographics fields in tblDemographicsCREATE PROCEDURE dbo.usp_UpdateDemographicsTable( -- The user ID is required, so it can be added to the usage log @pkUserID int, -- Use the application number or broker ID to lookup the demo ID @AppNumber int, @BrokerID int, -- Pass in all the demographics details @BrokerName varchar(100), @BrokerDbaNames varchar(100), @PrimaryContact varchar(20), @PhoneNumber varchar(25), @FaxNumber varchar(25), @EmailAddress varchar(255), @Address varchar(250), @City varchar(50), @fkStateId int, @Zip char(5), @fkTerritoryId int, @fkAssignAcctExecID int, @Website varchar(255), @TaxIdNumber varchar(11))ASSET NOCOUNT ONBEGIN TRANSACTION;-- Used for parsing all the column names during the updateDECLARE @column_list AS varchar(250);DECLARE @parsing_list AS varchar(250);DECLARE @current_column AS varchar(25);DECLARE @find_comma AS int;-- Createa list of all the demographics fieldsSELECT @column_list = "BrokerName, BrokerDbaNames, PrimaryContact, PhoneNumber, " + "FaxNumber, EmailAddress, Address, City, fkStateId, Zip, fkTerritoryId, " + "fkAssignAcctExecID, Website, TaxIdNumber";-- Pull the demographics ID for this application or broker profileDECLARE @demoID As int;IF @AppNumber IS NOT NULLBEGIN SELECT @demoID = fkDemoID FROM tblApplications WHERE pkApplicationNumber = @AppNumber;ENDELSE IF @BrokerID IS NOT NULLBEGIN SELECT @demoID = fkDemoID FROM tblBrokers WHERE pkBrokerID = @BrokerID;ENDELSEBEGIN RAISERROR 50000 'No Application number or Broker Profile Number was specified'; RETURN;END-- Loop through all the column namesSELECT @parsing_list = @column_list;WHILE @parsing_list IS NOT NULLBEGIN -- Retrieve the next column name SELECT @find_comma = PATINDEX('%,%', @parsing_list); IF @find_comma <> 0 BEGIN -- Pull the column from the list SELECT @current_column = SUBSTRING(@parsing_list, 1,(@find_comma - 1)); -- Remove the column from the list SELECT @parsing_list = dbo.Trim(SUBSTRING(@parsing_list, (@find_comma + 1), 250)); END ELSE BEGIN SELECT @current_column = @parsing_list; SELECT @parsing_list = NULL; END -- If the demographics entry has changed update it in the table and add an entry to the usage log EXEC(' IF @' + @current_column + ' <> (SELECT ' + @current_column + ' FROM tblDemographics WHERE pkDemoId = @demoID) BEGIN -- Add an entry to the usage log for either the application or broker ID INSERT INTO tblUsageLog ( fkApplicationNumber, fkBrokerID, DateTimeOfAction, fkUserID, Description ) Values ( @AppNumber, @BrokerID, GetDate(), @pkUserID, ''Changed ' + @current_column + ' from '' + (SELECT ' + @current_column + ' FROM tblDemographics WHERE pkDemoId = @demoID) + '' to '' + @' + @current_column + ' ); -- Update the values into the table UPDATE tblDemographics SET ' + @current_column + ' = @' + @current_column + ', WHERE pkDemoId = @demoID; END ')END-- Check for errors before committing the transactionIF @@ERROR <> 0BEGIN ROLLBACK TRANSACTION; RETURN -1;ENDELSEBEGIN COMMIT TRANSACTIONENDGO |
 |
|
|
Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)
7020 Posts |
Posted - 2006-01-25 : 18:56:42
|
I guess I don't see the point of the loop. You could just SELECT the current values from tblDemographics, and then do a single UPDATE to tblDemographics and a single INSERT into tblUsageLog from a SELECT .. UNION ALL where you send in one row for each column that changed. There is no need for Dynamic SQL at all.Also, the UPDATE to tblDemographics that you have in your code will not work, unless you change it to Dynamic SQL.-- Get current valuesselect @cur_BrokerName = BrokerName, @cur_BrokerDbaNames = BrokerDbaNames ... and so on...from tblDemographicswhere pkDemoId = @demoID-- update the rowupdate aset BrokerName = case when @BrokerName is not null and @BrokerName <> a.BrokerName then @BrokerName else a.BrokerName end, BrokerDbaNames = case when @BrokerDbaNames is not null and @BrokerDbaNames <> a.BrokerDbaNames then @BrokerDbaNames else a.BrokerDbaNames end, ... and so on...from tblDemographics awhere a.pkDemoId = @demoID-- Log changesINSERT INTO tblUsageLog ( fkApplicationNumber, fkBrokerID, DateTimeOfAction, fkUserID, Description )select @AppNumber, @BrokerID, GetDate(), @pkUserID, a.Descfrom ( select Desc = 'Changed BrokerName from '+ @cur_BrokerName+' to '+ @BrokerName where @BrokerName is not null and @BrokerName <> @cur_BrokerName union all select Desc = 'Changed BrokerDbaNames from '+ @cur_BrokerDbaNames+' to '+ @BrokerDbaNames where @BrokerDbaNames is not null and @BrokerDbaNames <> @cur_BrokerDbaNames union all ... and so on... ) a CODO ERGO SUM |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2006-01-26 : 00:48:27
|
"I usually will not click on a link like that. I don't know about other people, but I doubt if I'm the only one that feels that way"Although I'm sure that Billkamm's intention was good I too didn't click it (and don't click "ShortLink.com" URLs)"but it was large amount of code, so I did that link instead"Nah! Don't worry about that ...You could perhaps replaceIF @AppNumber IS NOT NULLBEGIN SELECT @demoID = fkDemoID FROM tblApplications WHERE pkApplicationNumber = @AppNumber;ENDELSE IF @BrokerID IS NOT NULLBEGIN SELECT @demoID = fkDemoID FROM tblBrokers WHERE pkBrokerID = @BrokerID;ENDELSEBEGIN RAISERROR 50000 'No Application number or Broker Profile Number was specified'; RETURN;END withIF @AppNumber IS NOT NULLBEGINSELECT @demoID = fkDemoIDFROM dbo.tblApplicationsWHERE (@AppNumber IS NULL OR pkApplicationNumber = @AppNumber) AND (@BrokerID IS NULL OR pkBrokerID = @BrokerID)IF @@ROWCOUNT = 0 -- Bit naughty, this is "No rows found" rather than "No parameters provided" !!BEGIN RAISERROR 50000 'No Application number or Broker Profile Number was specified'; RETURN;END (Note that explicitly naming the owner ("dbo.") will help the query planner use the cache more often)We do UpSerts like this:UPDATE DSET [MyColumn1] = S.[MyColumn1], [MyStringColumn2] = S.[MyStringColumn2], ...FROM dbo.MyDestinationTable AS D JOIN dbo.MySourceTable AS S ON D.[MyPKColumn] = S.[MyPKColumn]WHERE ( (D.[MyColumn1] <> S.[MyColumn1] OR (D.[MyColumn1] IS NULL AND S.[MyColumn1] IS NOT NULL) OR (D.[MyColumn1] IS NOT NULL AND S.[MyColumn1] IS NULL)) OR (D.[MyStringColumn2] COLLATE Latin1_General_BIN <> S.[MyStringColumn2] OR (D.[MyStringColumn2] IS NULL AND S.[MyStringColumn2] IS NOT NULL) OR (D.[MyStringColumn2] IS NOT NULL AND S.[MyStringColumn2] IS NULL)) )INSERT INTO dbo.MyDestinationTable( [MyPKColumn], [MyColumn1], [MyStringColumn2], ...)SELECT [MyPKColumn] = MyPKColumn, [MyColumn1] = MyColumn1, [MyStringColumn2] = MyStringColumn2, ...FROM dbo.MySourceTable SWHERE NOT EXISTS ( SELECT * FROM dbo.MyDestinationTable D WHERE D.[MyPKColumn] = S.[MyPKColumn] )ORDER BY S.MyPKColumn Kristen |
 |
|
|
Next Page
|