SQL Server 2008 throws "Declare table variable" errors - sql-server

SQL Server 2008 throws errors when trying to write following query to create a stored procedure:
DECLARE #T table (TimeId uniqueIdentifier)
INSERT INTO #T
SELECT DISTINCT ref1.value( './#v', 'uniqueIdentifier')
FROM #xmlTimeIds.nodes('/a/i') T(ref1)
UPDATE TAB1
SET TAB1.TMAT_INVOICED_HOURS = 0
FROM dbo.TMAT_TimeRegisterAttribute AS TAB1
INNER JOIN #T on TAB1.TMAT_AT_GUID = #T.TimeId
WHERE TAB1.TMAT_TN_GUID = #guidTenantId

Give #T an alias in the update sql. The compiler regards #T as a variable rather than a table.
DECLARE #T table (TimeId uniqueIdentifier)
INSERT INTO #T
SELECT DISTINCT ref1.value( './#v', 'uniqueIdentifier')
FROM #xmlTimeIds.nodes('/a/i') T(ref1)
UPDATE TAB1
SET TAB1.TMAT_INVOICED_HOURS = 0
FROM dbo.TMAT_TimeRegisterAttribute AS TAB1
INNER JOIN #T TempTable on TAB1.TMAT_AT_GUID = TempTable.TimeId
WHERE TAB1.TMAT_TN_GUID = #guidTenantId

You have on repeated twice: INNER JOIN #T on on TAB1.TMAT_AT_GUID = #T.TimeId. Should be like this:
DECLARE #T table (TimeId uniqueIdentifier)
INSERT INTO #T
SELECT DISTINCT ref1.value( './#v', 'uniqueIdentifier')
FROM #xmlTimeIds.nodes('/a/i') T(ref1)
UPDATE TAB1
SET TAB1.TMAT_INVOICED_HOURS = 0
FROM dbo.TMAT_TimeRegisterAttribute AS TAB1
INNER JOIN #T on TAB1.TMAT_AT_GUID = #T.TimeId
WHERE TAB1.TMAT_TN_GUID = #guidTenantId

Related

SQL Inner Join: Weird Result

I have data that looks like this:
Table_A:
Source tableName systemid
A table_1 123abcA2
B table_1 222DEFD3
C table_1 369CCCB3
Table_B:
Source tableName systemid
Q table_2 123abc
R table_2 222DEF
C table_2 369CCC
I ran the following query:
select a.Source, a.tableName, a.systemid as a_systemid, b.systemid as b_systemid
from table_a as a
inner join table_b as b on a.systemid = b.systemid
Here is what came back:
Source tableName a_systemid b_systemid
A table_1 123abcA2 123abc
B table_1 222DEFD3 222def
C table_1 369CCCB3 369CCC
Shouldn't I get nothing returned? As nothing matches.
Table A system id = nvarchar data type
Table b systemid = uniqueidentifier data type
Implicit casting is occuring and essentially truncating your string data which causes a match. You need to explicitly cast the uniqueidentifier to an nvarchar(max).
Please see this question and answer.
DECLARE #t1 TABLE([Source] CHAR(1),tableName VARCHAR(10),systemid nvarchar(max))
DECLARE #t2 TABLE([Source] CHAR(1),tableName VARCHAR(10),systemid uniqueidentifier)
INSERT INTO #t1 SELECT 'A','table_1','15b993cc-e8be-405d-bb9f-0c58b66dcdfe_1'
INSERT INTO #t1 SELECT 'B','table_1','4cffe724-3f68-4710-b785-30afde5d52f8_1'
INSERT INTO #t1 SELECT 'C','table_1','7ad22838-ddee-4043-8d1f-6656d2953545_1'
INSERT INTO #t2 SELECT 'Q','table_2','15b993cc-e8be-405d-bb9f-0c58b66dcdfe'
INSERT INTO #t2 SELECT 'R','table_2','4cffe724-3f68-4710-b785-30afde5d52f8'
INSERT INTO #t2 SELECT 'C','table_2','7ad22838-ddee-4043-8d1f-6656d2953545'
select a.Source, a.tableName, a.systemid as a_systemid, b.systemid as b_systemid
from #t1 as a
inner join #t2 as b on a.systemid = CONVERT(NVARCHAR(MAX),b.systemid)
As a practice, you should always explicitly cast mismatched datatypes for clarity as well as prevent weird "what is going on?!?!" stuff.

SQL Server exists not working in select statement

Query 1 below returns the correct result. But why does query2 return a wrong result? It looks like the exists in query2 doesn't work as expected. Tested on SQL Server 2016.
create table #t1 (id nvarchar(20), typ nvarchar(20))
insert into #t1
values ('1', 'stu'), ('2', 'exstu'), ('string', null)
create table #t2 (id int)
insert into #t2
values (1), (3)
--
--select * from #t1
--select * from #t2
--drop table #t1
--drop table #t2
-- Query #1:
select *
from #t1
where #t1.typ = 'stu' or typ = 'exstu'
and exists (select * from #t2
where #t1.id = #t2.id)
-- Query #2:
select *
from #t1
where exists (select * from #t2
where #t1.id = #t2.id)
and #t1.typ = 'stu' or typ = 'exstu'
AND takes precedence hence the last condition typ = 'exstu' in your second query causing and additional rows to be included in result set. Please check operator-precedence-transact-sql
Assuming you want both queries to give the same result, you'll need to add parentheses to your second query's WHERE clause to have the boolean logic match up:
select *
from #t1
where
exists (
select * from #t2
where #t1.id = #t2.id
)
and (#t1.typ = 'stu' or typ = 'exstu')

but give me error that invalid object name #temp2

Alter procedure spMRI_TAG_try
#DocNum int
as
declare #cnt int
declare #count int
declare #cardname nvarchar(100)
declare #Docdate datetime
declare #itemCode nvarchar(50)
declare #Dscription nvarchar(100)
declare #Quantity numeric(19,6)
declare #ManBtchNum char(1)
declare #SalPackUn numeric(19,6)
declare #ExpDate datetime
begin
set #cnt = 1
select #Count = pdn1.Quantity/OITM.SalPackUn from pdn1 inner join OITM on pdn1.ItemCode=OITM.ItemCode
while #cnt <= #count
insert into #temp2 values(#cardname,#DocDate,#itemcode,#Dscription,#Quantity,#ManBtchNum,#SalPackUn,#ExpDate)
select #cardname = a.CardName,#DocDate=a.DocDate,#itemcode=b.ItemCode,#Dscription=b.Dscription,#Quantity=b.Quantity,#ManBtchNum=c.ManBtchNum,#SalPackUn=c.SalPackUn,#ExpDate=d.ExpDate
from OPDN a inner join PDN1 b on a.DocEntry = b.DocEntry inner join OITM c on c.ItemCode = b.ItemCode inner join OBTN d on c.ItemCode = d.ItemCode and a.DocNum=#DocNum and d.ExpDate is not null
set #cnt=#cnt+1
end
select * from #temp2
but gives me an invalid object name #temp2 error.
Create temp table before your while loop:
create table #temp2 (Cardname ...)
while #cnt <= #count
insert into #temp2 values(#cardname,#DocDate,#itemcode,#Dscription,#Quantity,#ManBtchNum,#SalPackUn,#ExpDate)
select #cardname = a.CardName,#DocDate=a.DocDate,#itemcode=b.ItemCode,#Dscription=b.Dscription,#Quantity=b.Quantity,#ManBtchNum=c.ManBtchNum,#SalPackUn=c.SalPackUn,#ExpDate=d.ExpDate
Two points here:
Not sure why you are using looping - Try set based approaches. You can solve most of the problems in set based queries
You can create temp tables using select * into #temp2... Check for that syntax in msdn
To be honest your SP is a one big messed up code :)
I suggest you to rewrite it like this:
ALTER PROCEDURE spMRI_TAG_try
#DocNum int
AS
--Drop table if it exists
IF OBJECT_ID(N'#temp2') IS NOT NULL DROP TABLE #temp2
--create table
CREATE TABLE #temp2 (
cardname nvarchar(100),
Docdate datetime,
itemCode nvarchar(50),
Dscription nvarchar(100),
Quantity numeric(19,6),
ManBtchNum char(1),
SalPackUn numeric(19,6),
ExpDate datetime
)
--Make the insertion
INSERT INTO #temp2
SELECT a.CardName,
a.DocDate,
b.ItemCode,
b.Dscription,
b.Quantity,
c.ManBtchNum,
c.SalPackUn,
d.ExpDate
FROM OPDN a
INNER JOIN PDN1 b
ON a.DocEntry = b.DocEntry
INNER JOIN OITM c
ON c.ItemCode = b.ItemCode
INNER JOIN OBTN d
ON c.ItemCode = d.ItemCode and a.DocNum=#DocNum and d.ExpDate is not null
--output
SELECT *
FROM #temp2
No need a while loop (I can not even understand how you will switch through the rows, in your solution it will write the same row the '#count' times), you can write all data directly in temp table.
You get error because of there is no #temp2 table on the moment you are trying to insert, also there is no checking if the table already exists.
As was noted in answer by Kannan Kandasamy, the one more way is to use SELECT * INTO #temp2, it can be achieved this way:
ALTER PROCEDURE spMRI_TAG_try
#DocNum int
AS
IF OBJECT_ID(N'#temp2') IS NOT NULL DROP TABLE #temp2
SELECT a.CardName,
a.DocDate,
b.ItemCode,
b.Dscription,
b.Quantity,
c.ManBtchNum,
c.SalPackUn,
d.ExpDate
INTO #temp2
FROM OPDN a
INNER JOIN PDN1 b
ON a.DocEntry = b.DocEntry
INNER JOIN OITM c
ON c.ItemCode = b.ItemCode
INNER JOIN OBTN d
ON c.ItemCode = d.ItemCode and a.DocNum=#DocNum and d.ExpDate is not null
SELECT *
FROM #temp2

How to count number of employees with particular name in this query?

select table1.empname
,table11.empname
,table11.timeordertook
,Table1.saleApproved
,Table1.saleStatus
from Table1, table11
where Table1.empName = Table11.empName
I want to count the number of employees with particular Name in this query How to do this using ms sql query?
As simple as this:
select count(*)
from Table1
inner join table11 on Table1.empName = Table11.empName
where Table1.empName = 'Some name'
Try this:
Just Pass the employee name in the filter
declare #t table (Employee varchar (20))
insert into #t VALUES ('ale')
insert into #t VALUES ('ale')
insert into #t VALUES ('leg')
select count(*)
from #t
where Employee like 'ale'
--OR
--where Employee = 'ale'

How to merge XML in T-SQL?

It doesn't seem that any amount of reading the docs will help me. Consider the simplified example:
declare #table1 table ( id int, parent xml )
insert #table1 values( 1, '<Root></Root>' )
declare #table2 table ( id int, guts xml )
insert #table2 values( 1, '<Guts>hi mom!</Guts>' )
select t1.parent.query('')
from #table1 t1 inner join #table2 t2 on t1.id = t2.id
What would be passed to the query function to generate this result?
<Root><Guts>hi mom!</Guts></Root>
The following is not set based, but maybe it will help (SQL2008 only)
declare #table1 table ( id int, parent xml )
insert #table1 values( 1, '<Root></Root>' )
declare #table2 table ( id int, guts xml )
insert #table2 values( 1, '<Guts>hi mom!</Guts>' )
DECLARE #id int;
DECLARE #results table (id int, results xml);
DECLARE idCursor CURSOR FOR
select id from #table1
OPEN idCursor
FETCH NEXT FROM idCursor INTO #id
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #parent xml, #guts xml
SELECT #parent = parent FROM #table1 where id = 1;
SELECT #guts = guts FROM #table2 where id = 1;
SET #parent.modify('insert sql:variable("#guts") into (/Root[1])');
INSERT #results (id, results) values (#id, #parent);
FETCH NEXT FROM idCursor INTO #id
END
CLOSE idCursor
DEALLOCATE idCursor
select * from #results;
You are asking for an XML operation, not for a relational operation. What you want is to produce a new XML by inserting a fragment of XML into it, which means you have to use the xml.modify() method. Technically this is possible, but the modify() must be called within an update context, so it won't work in a SELECT. It can work in a SET or in an UPDATE:
UPDATE t1
SET parent.modify(N'insert sql:column("t2.guts") into (/Root)[1]')
FROM #table1 t1
JOIN #table2 t2 on t1.id = t2.id;
SELECT * from #table1;
If you must have the result in a SELECT then you'll have to shred the XML into relational table, join that and reconstruct the XML back using FOR XML.

Resources