This is probably super basic but I've never built a procedure where I'm writing to a table where I need to pull the next id. Can someone walk me through how to find the next id, assign it on the insert, and then make sure that the next id table gets updated?
Thanks in advance!
Depends: does this procedure insert individual rows, or does it need to insert a number of rows at once?
For the former, I believe that the stored procedure [dbo].[AP_GET_NEXTID_function] is the officially sanctioned method to acquire an id while incrementing the T_NEXT_ID table.
If you want to update a number of rows at once you can also use this with an increment, but will need to sort out distributing the ids for insertion yourself (I have some code for that if you'd like).
I'm looking to insert multiple rows at once. Basically, I'm copying info from one place to another because it needs to live in two places. Would love to see the code you use. Thanks!
I do this a fair amount: typically I create rows in a temporary table before inserting them into the table in question, which sounds like a good option if you're copying info from one place to another. Generally what you should do is:
Hi, take a look at this. im using next_id to auto create sources.
--select * from T_CAMPAIGN where description like 'DCM%' --campaign_no default_fund description --1688 NULL DCM Leads FY22 --select * from T_APPEAL where description like 'DCM%' --appeal_no campaign_no description --2593 1688 DCM Leads FY22 --select * from TX_APPEAL_MEDIA_TYPE where appeal_no = 2556 declare @createSources char(1) declare @appeal_no int declare @source_no int declare @source_name varchar(50) declare @segment_id int declare @source_Start_Dt datetime = DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0) -- begining of today set @appeal_no = 2593 -- 2593 1688 DCM Leads FY22 set @createSources = 'N' create table #new_Sources(id int identity(1,1), source_name varchar(50), source_name_len int, segment_id int, param_1 varchar(99), param_2 varchar(99)) insert into #new_Sources(source_name, source_name_len, segment_id, param_1, param_2) select 'DCM_' + left(isnull(b.Param_Name,'') + case when isnull(b.Param_Name,'') > '' and isnull(c.Param_Name,'') > '' then '/' else '' end + isnull(c.Param_Name,''),46), len('DCM_' + isnull(b.Param_Name,'') + case when isnull(b.Param_Name,'') > '' and isnull(c.Param_Name,'') > '' then '/' else '' end + isnull(c.Param_Name,'')), a.ID, b.Param_Name, c.Param_Name from [LTR_DCM_LEAD_SEGMENTS] a left outer join [LTR_DCM_LEAD_PARAMETERS] b on a.param_1 = b.id left outer join [LTR_DCM_LEAD_PARAMETERS] c on a.param_2 = c.id where a.inactive = 'N' select * from #new_Sources order by segment_id select 'Duplicate new source name' select * from #new_Sources where source_name in(select source_name from #new_Sources group by source_name having count(id) > 1) order by source_name if exists(select * from #new_Sources where source_name_len > 50) begin print 'Source_Name length Issue' return end if @createSources = 'Y' BEGIN declare @done char(1) declare @placeholder int select @done = 'N', @placeholder = 0 While @done = 'N' Begin Select @placeholder = min(id)from #new_Sources where id > @placeholder If @placeholder is null Select @done = 'Y' Else BEGIN TRY BEGIN TRANSACTION select @source_name = left(source_name,50), @segment_id = segment_id from #new_Sources where id = @placeholder if not exists(select * from TX_APPEAL_MEDIA_TYPE where appeal_no = @appeal_no and source_name = @source_name) begin -- create new source exec @source_no = [dbo].ap_get_nextid_function @type = 'SL' insert into TX_APPEAL_MEDIA_TYPE (appeal_no, media_type,source_no,source_name,acq_dt,source_type,source_group,inactive,num_success_cust,start_dt) select @appeal_no,32,@source_no,@source_name,@source_Start_Dt,'B',82,'N',0,@source_Start_Dt -- update segment with source update LTR_DCM_LEAD_SEGMENTS set Source_no = @source_no where id = @segment_id end COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; print 'bad shit happened' END CATCH End END --delete from TX_APPEAL_MEDIA_TYPE where source_no in (23338,23342) -- source_name varchar(50) -- select * from T_NEXT_ID where type = 'SL' /* type description next_id parent_table parent_col module SL Source List 23339 TX_APPEAL_MEDIA_TYPE source_no F */ drop table #new_Sources
Thanks!
I've tested this out and it works great but when I drop the table and try it again it hasn't updated T_NEXT_ID. I'm assuming I need to add a line to update that before I drop my table? Does that sound right? Or is there some other function I'm supposed to execute?
What table are you dropping? Also, is it possible you are rolling back a transaction before querying T_NEXT_ID? Here's an example adding 10 to the source_no for TX_APPEAL_MEDIA_TYPE:
declare @type char(2) = 'SL', @nextid int, @increment int = 10
select * from T_NEXT_ID where type = 'SL'
select @nextid as nextid_before
exec [dbo].[AP_GET_NEXTID_function] @type = @type, @nextid = @nextid output, @increment = @increment
select @nextid as nextid_after
I'm using a temp table to stage things and plan to drop the table in the sproc. How are you figuring out how many rows are going to be in your temp table to tell it what the increment should be? In my instance, the number will be different every time this sproc is run.
Right. Actually, these days I typically use a table variable. Before I would often take the table I was going to insert into, do a "select * into #temp_table from actual_table" to quickly get my columns, but as of a couple of sql versions ago that includes copying over constraints on the audit columns, and so now I just spell out the columns I'll actually be working with, and a table variable is a bit easier to work with. I then build out the new rows I want using the table variable, and then I can just count the resulting rows in the table variable to get the id count that I need, so something like:
declare @increment = 0
select @increment = (select COUNT(*) from @table_variable)
Ah, that totally makes sense! So if I have something like the following I should be all set, right?
declare @next_id int, @cs_count int SELECT @cs_count = Count(*) FROM #access exec @next_id = [dbo].ap_get_nextid_function @type = 'CT', @increment = @cs_count update #access set @next_id = id_key = @next_id + 1 where id_key = -1
Yes, that looks right to me.
Thanks again! I think I owe you a couple of drinks next time we are in the same city with all the help you've provided!
Alas for virtual beer. And no problem, just take a moment to sympathize: that script is an idealized process that I've only really sorted out in the past couple of years, meaning I have a decade's worth of procedures that should really work that way, but are instead wildly more awkward and at risk of collision...
This has been super informative. I usually cheat with individual records and use insert Max(ID)+1