SP Help (Invalid Column Name) - sql-server

With a MS SQL Stored Procedure I am getting the following error "Invalid Column Name NavigationID".
Can anyone let me know what I am doing incorrectly?
DECLARE #NavigationID INT
SET #NavigationID = 5
CREATE TABLE #tmp (NavigationID int , ParentID int);
INSERT INTO #tmp SELECT NavigationID, ParentID FROM Nav;
WITH Parent AS
(
SELECT NavigationID, ParentID FROM #tmp WHERE NavigationID = #NavigationID
UNION ALL
SELECT t.NavigationID, t.ParentID FROM Parent
INNER JOIN #tmp t ON t.NavigationID = Parent.ParentID
)
SELECT NavigationID FROM ParentID
WHERE NavigationID <> #NavigationID;

With the code you posted you get.
Msg 208, Level 16, State 1, Line 10
Invalid object name 'ParentID'.
Change FROM ParentID to FROM Parent.
You also need a column NavigationID in table Nav.
Try this:
declare #Nav table(NavigationID int, ParentID int)
insert into #Nav
select 1, null union all
select 2, 1 union all
select 3, 1 union all
select 4, 3 union all
select 5, 3 union all
select 6, null union all
select 7, 6
declare #NavigationID int;
set #NavigationID = 5;
with Parent as
(
select NavigationID,
ParentID
from #Nav
where NavigationID = #NavigationID
union all
select t.NavigationID, t.ParentID
from Parent
inner join #Nav t
on t.NavigationID = Parent.ParentID
)
select NavigationID
from Parent
where NavigationID <> #NavigationID;
Result:
NavigationID
------------
3
1
Replace #Nav with whatever table you are using. #Nav is only here so that this code can be copied and tested.

Related

How to get id's of parent ids for inserting children

I have Parent and Child table.
The goal is to duplicate the records, except with new primary keys.
Original Tables
Parent(id)
1
Child(id,parentId, data)
1,1
2,1
After insert:
Parent
1
2
Child
1,1
2,1
3,2
4,2
How do I do that? The part I am having trouble with is getting the new parent key for use with the child records.
This is what I have come up with so far.
--DECLARE VARS
declare #currentMetadataDocumentSetId int = 1, --Ohio
#newMetadataDocumentSetid int = 3; --PA
--CLEANUP
IF OBJECT_ID('tempdb..#tempFileRowMap') IS NOT NULL
/*Then it exists*/
DROP TABLE #tempFileRowMap
--Remove existing file row maps.
delete from file_row_map where metadata_document_set_id = #newMetadataDocumentSetid;
--Create a temptable to hold data to be copied.
Select [edi_document_code],
[functional_group],
[description],
3 as [metadata_document_set_id],
[document_name],
[incoming_file_row_subtype],
[metadata_document_id],
[document_subcode],
[outgoing_file_row_subtype],
[asi_type_code],
[asi_action_code],
[metadata_document_set],
file_row_map_id as orig_file_row_map_id
into #tempFileRowMap
from file_row_map fileRowMap
where metadata_document_set_id = #currentMetadataDocumentSetId;
--Select * from #tempFileRowMap;
Insert into file_row_map select
[edi_document_code],
[functional_group],
[description],
[metadata_document_set_id],
[document_name],
[incoming_file_row_subtype],
[metadata_document_id],
[document_subcode],
[outgoing_file_row_subtype],
[asi_type_code],
[asi_action_code],
[metadata_document_set]
from #tempFileRowMap
--Show Results
Select * from file_row_map fileRowMap where fileRowMap.metadata_document_set_id = #newMetadataDocumentSetid
--Update Detail
Select
[file_row_map_id],
[file_row_column],
[element_code],
[element_metadata_id],
[col_description],
[example],
[translate],
[is_used],
[is_mapped],
[page_num],
[subcode],
[qualifier],
[loop_code],
[loop_subcode],
[default_value],
[delete_flag]
into #tempFileRowMapDetail
from [dbo].[file_row_map_detail] d
left join #tempFileRowMap m
on m.orig_file_row_map_id = d.file_row_map_id
select * from #tempFileRowMapDetail
Simply use OUTPUT clause for getting exact Parent Table Primary Key values.
Lets build Example Schema for your case
--For Capturing inserted ID
CREATE TABLE #ID_CAPTURE (PARENT_ID INT,ORDER_NME VARCHAR(20));
--Your Intermidiate Data To insert into Actual Tables
CREATE TABLE #DUMMY_TABLE (ORDER_NME VARCHAR(20), ITEM_NME VARCHAR(20));
--Actual Tables
CREATE TABLE #ORDER_PARENT (ORDER_ID INT IDENTITY,ORDER_NME VARCHAR(20))
CREATE TABLE #ORDER_CHILD (CHILD_ID INT IDENTITY ,ORDER_ID INT, ORDER_NME VARCHAR(20))
INSERT INTO #DUMMY_TABLE
SELECT 'BILL1','Oil'
UNION ALL
SELECT 'BILL1', 'Gas'
UNION ALL
SELECT 'BILL2', 'Diesel'
Now do Inserts in Parent & Child Tables
INSERT INTO #ORDER_PARENT
OUTPUT inserted.ORDER_ID, inserted.ORDER_NME into #ID_CAPTURE
SELECT DISTINCT ORDER_NME FROM #DUMMY_TABLE
INSERT INTO #ORDER_CHILD
SELECT C.PARENT_ID, ITEM_NME FROM #DUMMY_TABLE D
INNER JOIN #ID_CAPTURE C ON D.ORDER_NME = C.ORDER_NME
SELECT * FROM #ID_CAPTURE
SELECT * FROM #ORDER_CHILD
There are other ways to get Inserted Identity values.
See documentation ##IDENTITY (Transact-SQL) , SCOPE_IDENTITY
Try following approach:
DECLARE #Table1 TABLE (
ID INT NOT NULL PRIMARY KEY,
ParentID INT NULL, -- FK
[Desc] VARCHAR(50) NOT NULL
);
INSERT #Table1 (ID, ParentID, [Desc])
VALUES
(1, NULL, 'A'),
(2, 1, 'AA.1'),
(3, 1, 'AA.2'),
(4, NULL, 'B'),
(5, 4, 'BB.1'),
(6, 4, 'BB.2'),
(7, 4, 'BB.3'),
(8, 7, 'BBB.1');
DECLARE #ParentID INT = 4;
DECLARE #LastID INT = (SELECT TOP(1) ID FROM #Table1 x ORDER BY x.ID DESC)
IF #LastID IS NULL
BEGIN
RAISERROR('Invalid call', 16, 1)
--RETURN ?
END
SELECT #LastID AS LastID;
/*
LastID
-----------
8
*/
DECLARE #RemapIDs TABLE (
OldID INT NOT NULL PRIMARY KEY,
[NewID] INT NOT NULL UNIQUE
);
WITH CteRecursion
AS (
SELECT 1 AS Lvl, crt.ID, crt.ParentID --, crt.[Desc]
FROM #Table1 crt
WHERE crt.ID = #ParentID
UNION ALL
SELECT cld.Lvl + 1 AS Lvl, crt.ID, crt.ParentID --, crt.[Desc]
FROM #Table1 crt
JOIN CteRecursion cld ON crt.ParentID = cld.ID
)
INSERT #RemapIDs (OldID, [NewID])
SELECT r.ID, #LastID + ROW_NUMBER() OVER(ORDER BY r.Lvl) AS [NewID]
FROM CteRecursion r;
--INSERT #Table1 (ID, ParentID, [Desc])
SELECT nc.[NewID] AS ID, np.[NewID] AS ParentID, o.[Desc]
FROM #Table1 o -- old
JOIN #RemapIDs nc /*new child ID*/ ON o.ID = nc.OldID
LEFT JOIN #RemapIDs np /*new parent ID*/ ON o.ParentID = np.OldID
/*
ID ParentID Desc
----------- ----------- --------------------------------------------------
9 NULL B
10 9 BB.1
11 9 BB.2
12 9 BB.3
13 12 BBB.1
*/
Note: with some minor changes should work w. many ParentIDs values.

Cannot update itself in SQL Server 2008 R2

Please see my sample as below:
create table tbl1(cl1 int, cl2 varchar(10))
create table tbl2(cl1 int, cl2 varchar(10))
insert tbl1
select 1, 'a' union all
select 1, 'b' union all
select 1, 'c' union all
select 1, 'd' union all
select 1, 'e'
insert tbl2
select 1, '' union all
select 1, '' union all
select 1, 'c' union all
select 1, '' union all
select 1, 'a'
select * from tbl1
select * from tbl2
update b
set b.cl2 = a.cl2
from tbl1 a inner join tbl2 b on a.cl1=b.cl1
where b.cl2 = '' and a.cl2 not in (select cl2 from tbl2 where tbl2.cl1 = a.cl1)
What I want is to update all empty value at cl2 column in tbl2 table with not duplicate values.
I tried to run as the script above, but it didn't work correct.
Please help me to find out the solution.
Thanks.
Try this script.
create table #tbl1(cl1 int, cl2 varchar(10))
create table #tbl2(cl1 int, cl2 varchar(10))
insert #tbl1
select 1, 'a' union all
select 1, 'b' union all
select 1, 'c' union all
select 1, 'd' union all
select 1, 'e'
insert #tbl2
select 1, '' union all
select 1, '' union all
select 1, 'c' union all
select 1, '' union all
select 1, 'a'
update b
set b.cl2 = a.cl2
from #tbl1 a inner join #tbl2 b on a.cl1=b.cl1
where b.cl2 = '' and a.cl2 not in (select t.cl2 from #tbl2 t where a.cl1 = a.cl1)
Select * from #tbl1
Select * from #tbl2

Entering 40000 rows in sql server through loop

I have to make a database system that is purely on SQL Server. It's about a diagnostic lab. It should contain at least 40,000 distinct patient records. I have a table named "Patient" which contains an auto-generated ID, Name, DOB, Age and Phone number. Our teacher provided us with a dummy stored procedure which contained 2 temporary tables that has 200 names each and in the end he makes a Cartesian product which is supposed to give 40,000 distinct rows. I have used the same dummy stored procedure and modified it according to our table. But the rows inserted are only 1260 every time. Each time we run the query it does not give us more than 1260 records. I have added a part of temporary name tables and the stored procedure.
Declare #tFirstNames Table( FirstName Varchar(50) Not Null )
Declare #tLastNames Table ( LastName Varchar(50) Not Null )
Declare #tNames Table ( Id Int Identity Not Null, Name Varchar(50) Not Null)
Insert Into #tFirstNames (FirstName)
Select 'Julianne' Union All Select 'Sharyl' Union All Select 'Yoshie'
Union All Select 'Germaine' Union All Select 'Ja' Union All
Select 'Kandis' Select 'Hannelore' Union All Select 'Laquanda' Union All
Select 'Clayton' Union All Select 'Ollie' Union All
Select 'Rosa' Union All Select 'Deloras' Union All
Select 'April' Union All Select 'Garrett' Union All
Select 'Mariette' Union All Select 'Carline' Union All
Insert Into #tLastNames (LastName)
Select 'Brown' Union All Select 'Chrichton' Union All Select 'Bush'
Union All Select 'Clinton' Union All Select 'Blair'
Union All Select 'Wayne' Union All Select 'Hanks'
Union All Select 'Cruise' Union All Select 'Campbell'
Union All Select 'Turow' Union All Select 'Tracey'
Union All Select 'Arnold' Union All Select 'Derick'
Union All Select 'Nathanael' Union All Select 'Buddy'
Insert Into #tNames
Select FirstName + ' ' + LastName
From #tFirstNames, #tLastNames
Declare #iIndex Integer
Declare #iPatientTotalRecords Integer
Declare #vcName Varchar(50)
Declare #iAge Integer
--Set #iIndex = 1
Select #iPatientTotalRecords = Max(Id), #iIndex = Min(Id) From #tNames
While #iIndex <= #iPatientTotalRecords
Begin
Select #vcName = Name From #tNames Where Id = #iIndex
Set #iAge = Cast( Rand() * 70 As Integer ) + 10
Insert into Patient values
(#vcName, #iAge,
Case Cast( Rand() * 3 As Integer)
When 0 Then 'Male'
When 1 Then 'Female'
Else 'Female'
End,
Cast( Rand() * 8888889 As Integer ) + 1111111, DateAdd ( year, -#iAge, GetDate()))
Set #iIndex = #iIndex + 1
End
Possible you miss type UNION ALL -
Select 'Julianne' Union All
Select 'Sharyl' Union All
Select 'Yoshie' Union All
Select 'Germaine' Union All
Select 'Ja' Union All
Select 'Kandis' --<-- missing union all
Select 'Hannelore' Union All
Select 'Laquanda' Union All
Select 'Clayton' Union All
Select 'Ollie' Union All
Select 'Rosa' Union All
Select 'Deloras' Union All
Select 'April' Union All
Select 'Garrett' Union All
Select 'Mariette' Union All
Select 'Carline'
Try this one (without WHILE and additional variables):
DECLARE #tFirstNames TABLE (FirstName VARCHAR(50) NOT NULL)
INSERT INTO #tFirstNames (FirstName)
VALUES
('Julianne'), ('Sharyl'), ('Yoshie'), ('Germaine'),
('Ja'), ('Kandis'), ('Hannelore'), ('Laquanda'), ('Clayton'),
('Ollie'), ('Rosa'), ('Deloras'), ('April'), ('Garrett'),
('Mariette'), ('Carline')
DECLARE #tLastNames TABLE (LastName VARCHAR(50) NOT NULL)
INSERT INTO #tLastNames (LastName)
VALUES
('Brown'), ('Chrichton'), ('Bush'), ('Clinton'),
('Blair'), ('Wayne'), ('Hanks'), ('Cruise'), ('Campbell'),
('Turow'), ('Tracey'), ('Arnold'), ('Derick'),
('Nathanael'), ('Buddy')
INSERT INTO dbo.Patient (...)
SELECT
-- Possible problem: String or binary data would be truncated
d.FLName -- <-- FirstName + LastName i.e. 50 + 1 + 50 = 101 chars
, d.Age
, Gender = CASE ABS(CAST((BINARY_CHECKSUM(NEWID(), NEWID())) AS INT)) % 3
WHEN 0 THEN 'Male'
ELSE 'Female'
END
, (ABS(CAST((BINARY_CHECKSUM(NEWID(), NEWID())) AS INT)) % 8888889) + 1111111
, BirthDay = CONVERT(VARCHAR(10), DATEADD( year, -d.Age, GETDATE()), 112)
FROM (
SELECT
FLName = f.FirstName + ' ' + l.LastName
, Age = (ABS(CAST((BINARY_CHECKSUM(f.FirstName, NEWID())) AS INT)) % 70) + 10
FROM #tFirstNames f
CROSS JOIN #tLastNames l
) d

Comparing two select statements

I need to write a stored procedure in T-SQL that would do the following:
Get a list of items related to a certain SectionID
Select and return all of the SectionIDs that have the same list of items or more (not less)
The table structure is as follows:
Section ID | Item Name
1 Item1
2 Item1
1 Item2
1 Item3
2 Item2
So if I pass 1 as an ID, this should not return anything as SectionID 2 only has 2 of the 3 items that SectionID = 1 has, but if I pass SectionID = 2 as the parameter, this should return SectionID = 1.
Hopefully, I explained that properly. What would be a good approach for this?
Here is a full example of what you need:
create table #test (
SectionID int,
ItemName varchar(10)
)
insert into #test values (1, 'Item1')
insert into #test values (2, 'Item1')
insert into #test values (1, 'Item2')
insert into #test values (1, 'Item3')
insert into #test values (2, 'Item2')
insert into #test values (3, 'Item1')
insert into #test values (3, 'Item2')
insert into #test values (3, 'Item3')
declare #test int
select #test = 3
declare #dist int
select #dist = count(distinct ItemName) from #test where SectionID = #test
select distinct t0.SectionID from #test t0
left join (select distinct SectionID, ItemName from #test where SectionID = #test) t1
on t0.ItemName = t1.ItemName and t0.SectionID != t1.SectionID
where t0.SectionID != #test
group by t0.SectionID
having count(distinct t1.ItemName) >= #dist
drop table #test
In your case you just need this part:
declare #test int
select #test = 3 --input argument from stored procedure
declare #dist int
select #dist = count(distinct ItemName) from tablename where SectionID = #test
select distinct t0.SectionID from tablename t0
left join (select distinct SectionID, ItemName from tablename where SectionID = #test) t1
on t0.ItemName = t1.ItemName and t0.SectionID != t1.SectionID
where t0.SectionID != #test
group by t0.SectionID
having count(distinct t1.ItemName) >= #dist
Assuming the following Table...
DECLARE #Sections AS TABLE (Id INT, Item VARCHAR(25))
INSERT INTO #Sections
(Id, Item)
SELECT 1, 'Item1'
UNION SELECT 2, 'Item1'
UNION SELECT 1, 'Item2'
UNION SELECT 1, 'Item3'
UNION SELECT 2, 'Item2'
You can do this...
DECLARE #SectionId INT, #ItemCount INT
SELECT #SectionId = 2 --You'd change this to whatever
, #ItemCount = 0
SELECT #ItemCount = COUNT(*)
FROM #Sections
WHERE Id = #SectionId
SELECT s.Id
FROM #Sections AS p
JOIN #Sections AS s
ON s.Id != p.Id
AND s.Item = p.Item
WHERE p.Id = #SectionId
GROUP BY s.Id
HAVING COUNT(*) >= #ItemCount

How to use CTE to map parent-child relationship?

Say I have a table of items representing a tree-like structured data, and I would like to continuously tracing upward until I get to the top node, marked by a parent_id of NULL. What would my MS SQL CTE (common table expression) look like?
For example, if I were to get the path to get to the top from Bender, it would look like
Comedy
Futurama
Bender
Thanks, and here's the sample data:
DECLARE #t Table(id int, description varchar(50), parent_id int)
INSERT INTO #T
SELECT 1, 'Comedy', null UNION
SELECT 2, 'Futurama', 1 UNION
SELECT 3, 'Dr. Zoidberg', 2 UNION
SELECT 4, 'Bender', 2 UNION
SELECT 5, 'Stand-up', 1 UNION
SELECT 6, 'Unfunny', 5 UNION
SELECT 7, 'Dane Cook', 6
it should look like this:
declare #desc varchar(50)
set #desc = 'Bender'
;with Parentage as
(
select * from #t where description = #desc
union all
select t.*
from #t t
inner join Parentage p
on t.id = p.parent_id
)
select * from Parentage
order by id asc --sorts it root-first

Resources