SQL Server 2008
I have a table with 2 fields among others
TableA
alterid uniqueidentifier
revnum varchar(50)
Another table has the exact fields as the first one
TableB
alterid uniqueidentifier
revnum varchar(50)
I want to check compare the revnum fields. For each record of TableA I check if there is a record in TableB. If it exists and the revnum fields are different I update the TableB.revnum to the TebleA.revnum. If it does not exist then I add the record from TableA to TableB.
Here is the code
BEGIN
SET #Prod_curs =CURSOR FOR SELECT s.alterid, s.revnum, r.revnum FROM TableA s LEFT OUTER JOIN
TableB r ON s.alterid=r.alterid
WHERE s.revnum<>r.revnum OR r.revnum IS NULL
OPEN #Prod_curs
FETCH NEXT FROM #Prod_curs INTO #alterid, #srevnum, #rrevnum
WHILE ##FETCH_STATUS=0
BEGIN
IF #rrevnum IS NULL
BEGIN
INSERT INTO TableB (alterid,revnum) VALUES (#alterid,ISNULL(#srevnum,0))
END
IF #srevnum<>#rrevnum
BEGIN
UPDATE TableB SET revnum=#srevnum WHERE alterid=#alterid
END
FETCH NEXT FROM #Prod_curs INTO #alterid, #srevnum, #rrevnum
END
CLOSE #Prod_curs;
DEALLOCATE #Prod_curs;
END
My code works fine in a set of about 15000 records except some records where a weird thing happens.
In TableA I have this record
alterid revnum
'A770B280-B4DA-4937-9046-B24E60259AB6' '2-414922-1--1-1-2-51-0'
When it is store in TableB the values are
alterid revnum
'BF18A0EB-A684-486B-B053-55BC2969F1E3' '2-414922-1--1-1-2-51-0'
For some reason the alterid changes and I can't figure out why.
Can someone help
seems like code is working fine its just select that you are doing after insert/update.
i do have some unclear thing in your post as well.
Does the column "revnum" is primary key or has unique constraint on it in TableB ?
the result you have shown what is the select stmt you use for TableB ?
was it something like "Select top 1 * from TABLEB where revnum=xyz" ?
i ran you logic on dummy data and update/insert is fine.
check this code. what i doubt is in TABLEB you already have some "AlterID" with same "rvnum" value that is not present in "TableA"
see the below result where instead (3,3) i am also seeing (4,3)
SET NOCOUNT ON
DECLARE #t1 TABLE
(
id INT
,VALUE INT
)
INSERT INTO #t1 ( id, VALUE )
SELECT 1,1 UNION ALL SELECT 2,2 UNION ALL SELECT 3,3
DECLARE #t2 TABLE
(
id INT
,VALUE INT
)
INSERT INTO #t2 ( id, VALUE )
SELECT 1,1 UNION ALL SELECT 2,2 UNION ALL SELECT 4,3
DECLARE #Value1 INT,#Value2 INT,#ID INT ,#Prod_curs CURSOR
SET #Prod_curs =CURSOR FOR
SELECT s.id, s.Value, r.value
FROM #t1 s LEFT OUTER JOIN
#t2 r ON s.id=r.ID
WHERE s.Value<>r.Value OR r.Value IS NULL
OPEN #Prod_curs
FETCH NEXT FROM #Prod_curs INTO #ID, #Value1, #Value2
WHILE ##FETCH_STATUS=0
BEGIN
IF #Value2 IS NULL
BEGIN
INSERT INTO #T2 (ID,Value) VALUES (#ID,ISNULL(#Value1,0))
END
IF #Value1<>#Value2
BEGIN
UPDATE #T2 SET Value=#Value2 WHERE ID=#ID
END
FETCH NEXT FROM #Prod_curs INTO #ID, #Value1, #Value2
END
CLOSE #Prod_curs;
DEALLOCATE #Prod_curs;
SELECT TOP 1 * FROM #t2 WHERE VALUE = 3
Related
CREATE PROC [dbo].[usp_InsertBulkShipmentData]
(
#RetVal VARCHAR(1000) OUTPUT,
#ship dbo.ShipmentData READONLY
)
AS
DECLARE #ShipmentID BIGINT
Declare #Output table (id int)
BEGIN
INSERT INTO
dbo.Shipment (ShipmentType,scaccode,ShipmentControl,countryLoading,PortLoading,ShipperName,ShipperAddressOne,ShipperCity,ShipperCountry,ShipperProvince,
ShipperZip,ShipperPhone,ShipperEmail,ConsigneeName,ConsigneeAddressOne,ConsigneeCity,ConsigneeCountry,ConsigneeState,ConsigneeZip,
ConsigneePhone,ConsigneeEmail,ResponseCode,astrayExportDate,bondType,bondDestPort,bondOnwardscac,bondCarrierIRS,
bondNumber,bondTransferIRS,bondForeignPort,bondDepartureDate,MexiPediNumber)
OUTPUT Inserted.id into #Output
SELECT sh.DDcode,s.SCACCode,s.ShipmentControl,s.CountryLoading,s.ProvinceLoading,s.ShipperName,s.ShipperAddress,s.ShipperCity,s.ShipperCountry,s.ShipperProvince,
s.ShipperZip,s.ShipperPhone,s.ShipperEmail,s.ConsigneeName,s.ConsigneeAddressOne,s.ConsigneeCity,s.ConsigneeCountry,s.ConsigneeState,s.ConsigneeZip,
s.ConsigneePhone,s.ConsigneeEmail,s.CustomControl,s.DateShipmentLeft,s.InbondEntryType,s.InbondDestination,s.OnwardCarrier,s.BondCarrier,
s.Inbond,s.bondTransfer,s.ForeignPortDestination,s.EstimatedDeparture,s.MexiPediNumber
FROM #ship s INNER JOIN ShipmentTypeDropDown sh on sh.DisplayName=s.ShipmentType
select id from #Output
SET #RetVal = 'true|Record Inserted Successfully|'
END
BEGIN
SELECT #ShipmentID=id;
INSERT INTO dbo.Ship_commodity([Description],Quantity,manifestUnitCode,
[weight],weightUnitCode,countryCode,customsShipmentValue,commodityCode,MarksNumbers)
SELECT sp.CommoditiesDescription,sp.Quantity,qu.DDCode,sp.
[Weight],wu.DDCode,sp.CountryOrigin,sp.Value,sp.HarmonizedCode,sp.MarksNumbers
FROM #ship sp INNER JOIN WeightUnitDropDown wu on wu.DisplayName=sp.WeightUnitCode
INNER JOIN QuantityUnitDropDown qu on qu.DisplayName=sp.QuantityUnit
END
id is autogenerated in Shipment table. I wan to insert this id into Ship_commodity where ShipmentID=id.
I am inserting the records from user defined datatable, for every record , id is generated in Shipment table. When inserting into
Ship_commodity table i want to insert the Shipment id for every record , where ShipmentID=id.
How should i achieve this? please suggest.
In your first insert, you need to get the primary key of #ship to be able to join the output table to it (make sure to add extra columns to #output):
OUTPUT inserted.id, inserted.scaccode, inserted.ShipmentControl into #Output
Then you can join #output to #ship (i'm assuming Ship_commodity has a column fkShipmentId):
INSERT INTO dbo.Ship_commodity
(fkShipmentId, [Description], Quantity, manifestUnitCode, [weight], weightUnitCode,
countryCode, customsShipmentValue, commodityCode, MarksNumbers)
SELECT
i.id,
sp.CommoditiesDescription,
sp.Quantity,
qu.DDCode,
sp.[Weight],
wu.DDCode,
sp.CountryOrigin,
sp.Value,
sp.HarmonizedCode,
sp.MarksNumbers
FROM #ship sp
INNER JOIN WeightUnitDropDown wu on wu.DisplayName=sp.WeightUnitCode
INNER JOIN QuantityUnitDropDown qu on qu.DisplayName=sp.QuantityUnit
INNER JOIN #output i ON i.scaccode = sp.scaccode AND i.ShipmentControl = sp.ShipmentControl;
I have a table (Table1) that has 4 columns (ID1, ID2, Percent, Time, Expired). I want to insert a bunch of new rows in that table where ID1 is taken from another SQL query I have and all the other columns are set to some specified values.
So I have my query:
SELECT someID FROM other_tables WITH other_conditions
And essentially what I want to do is
FOR v in <above query>
Insert New row into Table1 (v, some second id, some percent, some time, some expired value)
EDIT I'm not opposed to not doing this in a loop, just don't know what the best way to insert the data is
You can use a cursor and fetch I think for what you are trying to accomplish. Here is a shell for you...
WITH CURSOR
DECLARE c CURSOR FOR
SELECT DISTINCT colName FROM Table1 JOIN Table2 ON <stuff> WHERE <other_stuff>
DECLARE #ID VARCHAR(4) --or what ever is needed
OPEN c
FETCH NEXT FROM c INTO #ID
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO Table1 (ID, ID2, Percent, Time, Expired)
VALUES (#ID, some second id, some percent, some time, some expired value)
WHERE ID = #ID
FETCH NEXT FROM c INTO #ID
END
CLOSE c
DEALLOCATE c
WITH CROSS APPLY (DUMMY DATA)
if object_id('tempdb..#ids') is not null drop table #ids
if object_id('tempdb..#idDetails') is not null drop table #idDetails
create table #ids (id int)
insert into #ids (id) values
(1),(2),(3)
select i.*, d.*
into #idDetails
from #ids i cross apply (select 2 as id2 ,2.0 as per,'1/1/2016' as dt,'x' as x) d
select * from #idDetails
WITH CROSS APPLY (EXAMPLE WITH YOUR TABLES)
select i.someID, d.*
into #idDetails
from other_tables i
cross apply (select 'some second id' as id2 ,'some percent' as [Percent],'1/1/2016 14:55:22' as [SomeTime] as dt,'SomeExpiredVal' as [ExpiredVal]) d
select * from #idDetails
Maybe I am missing something, but you need a table valued function which returns the desired row for each row in Table1
create function fn_get_new_recs(id int)
RETURNS #results TABLE (Id INT,<other columns you need>)
AS
BEGIN
--Query here to return new records for a single id
END
then use CROSS APPLY
INSERT INTO Table1(Id,Col1,Col2,Col3)
SELECT ST.Id,ST.Col1,ST.Col2,ST.Col3
FROM Table1 T
cross apply fn_get_new_recs(T.Id) ST
I have a table as follows
cat_id Cat_Name Main_Cat_Id
1 veg null
2 main course 1
3 starter 1
4 Indian 2
5 mexican 2
6 tahi 3
7 chinese 3
8 nonveg null
9 main course 8
10 indian 9
11 starter 8
12 tahi 11
13 chinese 11
(Main_Cat_Id is cat_id of previously added category in which it belongs)
This table is used for the categories the product where veg category has the two sub category main course and starter which is identify by main_cat_id
and those subcategories again has sub category as indian and mexican
And this categorization is dependent on the user; he can add more sub categories to indian, mexican also so that he can have any level of categorization
now I have to select all the subcategories of any node like if I take veg i have to select
(1)veg > (2)main course(1) > (4)indian(2)
> (5)mexican(2)
> (3)starter(1) > (6)thai(3)
> (7)chinese(3)
to form the string as 1,2,4,5,3,6,7
to do this i wrote a sql function as
CREATE FUNCTION [dbo].[GetSubCategory_TEST]
( #MainCategory int, #Category varchar(max))
RETURNS varchar(max)
AS
BEGIN
IF EXISTS (SELECT Cat_Id FROM Category WHERE Main_Cat_Id=#MainCategory)
BEGIN
DECLARE #TEMP TABLE
(
CAT_ID INT
)
INSERT INTO #TEMP(CAT_ID) SELECT Cat_Id FROM Category WHERE Main_Cat_Id=#MainCategory
DECLARE #TEMP_CAT_ID INT
DECLARE CUR_CAT_ID CURSOR FOR SELECT CAT_ID FROM #TEMP
OPEN CUR_CAT_ID
WHILE 1 =1
BEGIN
FETCH NEXT FROM CUR_CAT_ID
INTO #TEMP_CAT_ID;
IF ##FETCH_STATUS <> 0
SET #Category=#Category+','+ CONVERT(VARCHAR(50), #TEMP_CAT_ID)
SET #Category = [dbo].[GetSubCategory](#TEMP_CAT_ID,#Category)
END
CLOSE CUR_CAT_ID
DEALLOCATE CUR_CAT_ID
END
return #Category
END
but this function keep on executing and not gives the desired output i don't understands what wrong is going on plz help me to get this
You dont need a recursive function to build this, you can use a Recursive CTE for that.
Something like
DECLARE #TABLE TABLE(
cat_id INT,
Cat_Name VARCHAR(50),
Main_Cat_Id INT
)
INSERT INTO #TABLE SELECT 1,'veg',null
INSERT INTO #TABLE SELECT 2,'main course',1
INSERT INTO #TABLE SELECT 3,'starter',1
INSERT INTO #TABLE SELECT 4,'Indian',2
INSERT INTO #TABLE SELECT 5,'mexican',2
INSERT INTO #TABLE SELECT 6,'tahi',3
INSERT INTO #TABLE SELECT 7,'chinese',3
INSERT INTO #TABLE SELECT 8,'nonveg',null
INSERT INTO #TABLE SELECT 9,'main course',8
INSERT INTO #TABLE SELECT 10,'indian',9
INSERT INTO #TABLE SELECT 11,'starter',8
INSERT INTO #TABLE SELECT 12,'tahi',11
INSERT INTO #TABLE SELECT 13,'chinese',11
;WITH Recursives AS (
SELECT *,
CAST(cat_id AS VARCHAR(MAX)) + '\' ID_Path
FROM #TABLE
WHERE Main_Cat_Id IS NULL
UNION ALL
SELECT t.*,
r.ID_Path + CAST(t.cat_id AS VARCHAR(MAX)) + '\'
FROM #TABLE t INNER JOIN
Recursives r ON t.Main_Cat_Id = r.cat_id
)
SELECT *
FROM Recursives
I am ashamed, but I used #astander scipt to give string result.
First I created data you gave.
Second I collect rows which I need
And then using XML I put everything in one row (function STUFF removes first comma)
DECLARE #TABLE TABLE(
cat_id INT,
Cat_Name VARCHAR(50),
Main_Cat_Id INT
)
DECLARE #Collected TABLE(
cat_id INT
)
INSERT INTO #TABLE SELECT 1,'veg',null
INSERT INTO #TABLE SELECT 2,'main course',1
INSERT INTO #TABLE SELECT 3,'starter',1
INSERT INTO #TABLE SELECT 4,'Indian',2
INSERT INTO #TABLE SELECT 5,'mexican',2
INSERT INTO #TABLE SELECT 6,'tahi',3
INSERT INTO #TABLE SELECT 7,'chinese',3
INSERT INTO #TABLE SELECT 8,'nonveg',null
INSERT INTO #TABLE SELECT 9,'main course',8
INSERT INTO #TABLE SELECT 10,'indian',9
INSERT INTO #TABLE SELECT 11,'starter',8
INSERT INTO #TABLE SELECT 12,'tahi',11
INSERT INTO #TABLE SELECT 13,'chinese',11
INSERT INTO #TABLE SELECT 14,'chinese',6
DECLARE #nodeID INT = 1;
DECLARE #result VARCHAR(MAX);
;WITH Recursives AS (
SELECT cat_id, main_cat_id
FROM #TABLE
WHERE Cat_Id = #nodeID
UNION ALL
SELECT T.cat_id, T.main_cat_id
FROM #TABLE AS T
INNER JOIN Recursives AS R
ON t.Main_Cat_Id = r.cat_id
)
INSERT INTO #Collected
SELECT cat_id
FROM Recursives
SELECT #result = STUFF(
(SELECT ',' + CAST( cat_id AS VARCHAR)
FROM #Collected
ORDER BY cat_id
FOR XML PATH('')
), 1,1,'')
SELECT #result
Your cursor is looping infinitely because you asked it to keep going until 1 no longer equals 1:
WHILE 1 =1
1=1 is always true so the loop never ends, and you don't explicitly break out of it anywhere.
You would do well to study some examples of cursors, for example this one in the Microsoft T-SQL documentation. They are quite formulaic and the main syntax rarely needs to vary much.
The standard approach after opening the cursor is to do an initial fetch next to get the first result, then open a while loop conditional on ##FETCH_STATUS = 0 (0 meaning successful).
Because you're looking only for unsuccessful cursor fetch states inside your cursor:
IF ##FETCH_STATUS <> 0
The setting of #Category will only happen once the cursor has gone past the last row in the set. I suspect this is exactly what you don't want.
I'm also not sure about the scoping of the #Category variable, since it's an input parameter to the function; I generally create new variables inside a function to work with, but off the top of my head I'm not sure this will actually create a problem or not.
More generally, although I don't totally understand what you're trying to achieve here, a recursive function involving a cursor is probably not the right way to do it, as Adriaan Stander's answer suggests.
create table #sample (rowguid int identity ,id_frm int ,id_to int)
insert into #sample values( 1,5)
insert into #sample values( 7,13)
insert into #sample values( 17,20)
In the above table I have values starting Id and Ending Id. I need to prepare a table which has all the numbers falls between starting Id and Ending Id
i have tried it with looping but response is very slow in real world.
any body help me with query ???
This is what I have tried so far...
declare #sql varchar(8000) = '
select top '+cast((select max(id_to) from #sample) as varchar(100))+' identity(int,1,1) as guidid into tally from sysobjects,syscolumns '
exec (#sql)
alter table Tally add slab varchar(10)
create clustered index idx on Tally(guidid)
create clustered index idx on #sample(id_frm asc,id_to desc)
update Tally set slab = rowguid
from #sample join Tally on guidid between id_frm and id_to
delete from Tally where slab is null
select * from Tally
This query works fine with small numbers
But My real time table have 13 digit nos. It through Arithmetic overflow error
Assuming the range id_frm and id_to is relatively small integers, e.g. < 1M, one technique to approach this problem is to create a table with all values in the range and join to it:
WITH lotsOfNumbers AS
(
SELECT ROW_NUMBER() OVER (ORDER BY o1.object_id) AS id
FROM sys.objects o1 CROSS JOIN sys.objects o2
)
INSERT INTO #targetTable
SELECT l.ID
FROM lotsOfNumbers l
INNER JOIN #sample
ON l.ID BETWEEN #sample.id_frm AND #sample.id_to;
SqlFiddle here
A permanent table with the necessary range of ID's and a clustered index on the ID would improve performance, obviously.
Add in a DISTINCT if your ranges overlap, and you don't want duplicates in the result.
If you are able to get a full range of acceptable values into another table, you can use it without looping. The meathod below gets the minimum (1) and maximum (20), and the temporary table named #range will return everything in between.
drop table #sample
drop table #range
create table #sample (id_frm int ,id_to int)
insert into #sample values( 1,5)
insert into #sample values( 7,13)
insert into #sample values( 17,20)
create table #range (id int)
insert into #range select 1
go
insert into #range select top 1 max(id)+ 1 from #range
go 100
declare #min int
declare #max int
set #min= (select min(id_frm ) from #sample )
set #max = (select max(id_to) from #sample )
select * from #range where id between #min and #max
I need to know if all rows from one table exists in other:
declare #Table1 table (id int)
declare #Table2 table (id int)
insert into #Table1(id) values (1)
insert into #Table1(id) values (4)
insert into #Table1(id) values (5)
insert into #Table2(id) values (1)
insert into #Table2(id) values (2)
insert into #Table2(id) values (3)
if exists (select id from #Table1 where id in (select id from #Table2))
select 'yes exists'
else
select 'no, doesn''t exist'
This query returns yes exists but should return no, doesn't exist because only 1 exists in #Table2, values 4 and 5 don't.
What should I change in my query? Thanks!
IF NOT EXISTS (
SELECT ID FROM #Table1
EXCEPT
SELECT ID FROM #Table2
)
SELECT 'yes exists'
ELSE SELECT 'no, doesn''t exist'
You could use EXCEPT to get the set difference of both tables. If any ID's are returned, both tables are not equal:
SELECT ID
FROM #Table1
EXCEPT
SELECT ID
FROM #Table2
EXCEPT returns any distinct values from the left query that are not also found on the right query.
So, to get your "no, doesnt exist":
;WITH diff AS(
SELECT ID
FROM #Table1
EXCEPT
SELECT ID
FROM #Table2
)
SELECT CASE WHEN COUNT(diff.ID) = 0
THEN 'yes exists'
ELSE 'no, doesnt exist'
END AS Result
FROM diff
select case when count(*) > 0 then 'no' else 'yes' end as AllExist
from #Table1 t1
left outer join #Table2 t2 on t1.id = t2.id
where t2.id is null
This would work as long as both id columns are unique (which they should be if they are id's)
DECLARE #totalRows int;
SET #totalRows = SELECT count(*) from Table1;
RETURN (#totalRows == SELECT count(*) from Table1 JOIN Table2 on Table1.id = Table2.id)