Scalar Variable error using var Table but not Temp Table - sql

I am stumped with this one. I have the following code it works fine up to the point of the last #POC_XLATE in the update statement and then I get the error MUST DECLARE SCALAR VARIABLE.
If I change the table to a temp table the code works fine. I have tried moving the select statement to the end of the code, that didn't work. Hope someone has some suggestion on why it is doing this. Thanks in advance.
declare #POC_XLATE as TABLE(
POC_XLATE_ID int NULL,
TAR_ID int NULL,
POC_USERID varchar(50) NULL,
ACTION_DATE datetime NULL
)
insert into #POC_XLATE(POC_XLATE_ID, TAR_ID, POC_USERID, ACTION_DATE)
select * from POC_XLATE
where POC_XLATE.ACTION_DATE is null
select * from #POC_XLATE
update #POC_XLATE
set ACTION_DATE = TAR_DATA.OPEN_DATE
from TAR_DATA
where #POC_XLATE.TAR_ID = TAR_DATA.TAR_ID

A column alias cannot start with a #. That is the sign for a declared scalar variable. So, use table aliases:
update p
set ACTION_DATE = td.OPEN_DATE
from #POC_XLATE p JOIN
TAR_DATA td
on p.TAR_ID = td.TAR_ID ;
But why you would write the query in two steps?
insert into #POC_XLATE(POC_XLATE_ID, TAR_ID, POC_USERID, ACTION_DATE)
select p.POC_XLATE_ID, p.TAR_ID, p.POC_USERID, td.OPEN_DATE
from POC_XLATE p left join
TAR_DATA td
on p.TAR_ID = td.TAR_ID
where p.ACTION_DATE is null;
One step is much cleaner than two.

Related

SQL: Improving the string split

I have a set of code that takes a string value, split it, and pass it to a table. The code works, but it runs slow. Any suggestion to modify the code and make it run faster would be greatly appreciated.
DECLARE #StrPropertyIDs VARCHAR(1000)
SET #StrPropertyIDs = '419,429,459'
DECLARE #TblPropertyID TABLE
(
property_id varchar(100)
)
INSERT INTO #TblPropertyID(property_id)
select x.Item
from dbo.SplitString(#StrPropertyIDs, ',') x
select *
from vw_nfpa_firstArv_RPT
where property_use IN
(
SELECT property_id
FROM #TblPropertyID
)
The best long term strategy here would be to move away from CSV data in your SQL tables if at all possible. As a quick fix here, we could try creating the table variable with an index on property_id:
DECLARE #TblPropertyID TABLE (
property_id varchar(100) INDEX idx CLUSTERED
);
This would make the WHERE IN clause of your query faster, though we could try rewriting it using EXISTS:
SELECT *
FROM vw_nfpa_firstArv_RPT t1
WHERE EXISTS (SELECT 1 FROM #TblPropertyID t2
WHERE t2.property_id = t1.property_use);
Note that this would only work on SQL Server 2014 or later.

The multi-part identifier could not be bound error when assigning a variable

I have looked at several posts regarding the cause of this error and they all seem to point to aliases not being used to identify columns.
SELECT JM.Job_Number, JM.Project_Manager, JM.Superintendent,
ECL.Employee_Name AS PM_Name, ECL2.Employee_Name AS Supt_Name
FROM SPECTRUM.Spectrum.dbo.JC_JOB_MASTER_MC JM
LEFT OUTER JOIN SPECTRUM.Spectrum.dbo.Z_EMPLOYEE_CODE_LIST ECL
ON LTRIM(RTRIM(JM.Project_Manager)) = LTRIM(RTRIM(ECL.Employee_Code))
LEFT OUTER JOIN SPECTRUM.Spectrum.dbo.Z_EMPLOYEE_CODE_LIST ECL2
ON LTRIM(RTRIM(JM.Superintendent)) = LTRIM(RTRIM(ECL2.Employee_Code))
WHERE JM.Company_Code = 'ABC' AND JM.Status_Code = 'A' AND JM.Job_Number = '29-0018-00'
DECLARE
#test varchar(50) = ''
set #test = JM.Project_Manager
PRINT(#test)
The select portion of this runs fine but once I add in the set #test = JM.Project_Manager line I receive the error. Any ideas?
You should set the variable in the select statement:
DECLARE #test varchar(50) = '';
SELECT #test = JM.Project_Manager
FROM SPECTRUM.Spectrum.dbo.JC_JOB_MASTER_MC JM LEFT JOIN
SPECTRUM.Spectrum.dbo.Z_EMPLOYEE_CODE_LIST ECL
ON LTRIM(RTRIM(JM.Project_Manager)) = LTRIM(RTRIM(ECL.Employee_Code)) LEFT JOIN
SPECTRUM.Spectrum.dbo.Z_EMPLOYEE_CODE_LIST ECL2
ON LTRIM(RTRIM(JM.Superintendent)) = LTRIM(RTRIM(ECL2.Employee_Code))
WHERE JM.Company_Code = 'ABC' AND JM.Status_Code = 'A' AND JM.Job_Number = '29-0018-00';
In a SELECT, you can either assign variables or you can return a result set, but not both. You may want other variables for the other columns.
Your code doesn't work because JM is not defined in a SET statement. There is no connection to the previous SELECT.
You need variable but table variable which can hold multiple Project_Managers. So, this would be :
declare #projectmanager table (
Project_Manager varchar(255) )
insert into #projectmanager (Project_Manager)
select JM.Project_Manager
from . . . <rest part of query >;
select *
from #projectmanager;
For your current attempt JM.Project_Manager is actually missing. SQL Server can't find it as it is actually part of SELECT Statement. and the other thing is that you can't assign value to single variable in this way.

SQL Merge not inserting new row

I am trying to use T-SQL Merge to check for the existence of records and update, if not then insert.
The update works fine, but the insert is not working.
Any and all help on this would be gratefully received.
DECLARE
#OperatorID INT = 2,
#CurrentCalendarView VARCHAR(50) = 'month';
WITH CTE AS
(
SELECT *
FROM dbo.OperatorOption
WHERE OperatorID = #OperatorID
)
MERGE INTO OperatorOption AS T
USING CTE S ON T.OperatorID = S.OperatorID
WHEN MATCHED THEN
UPDATE
SET T.CurrentCalendarView = #CurrentCalendarView
WHEN NOT MATCHED BY TARGET THEN
INSERT (OperatorID, PrescriptionPrintingAccountID, CurrentCalendarView)
VALUES (#OperatorID, NULL, #CurrentCalendarView);
When would a row Selected from OperatorOption not already exist in OperatorOption?
If you're saying this code does not insert - you're right it doesn't because the row has to be there to begin with (in which case it won't insert), or the row is not there to begin with, in which case there is nothing in the source dataset to insert.
Does
SELECT *
FROM dbo.OperatorOption
WHERE OperatorID = #OperatorID
return anything or not?
This does not work the way you think it does. There is nothing in the source CTE.
The answer to 'was a blank dataset missing from the target' is 'No' so nothing is inserted
To do this operation, I use this construct:
INSERT INTO dbo.OperatorOption
(OperatorID, PrescriptionPrintingAccountID, CurrentCalendarView)
SELECT #OperatorID, NULL, #CurrentCalendarView
WHERE NOT EXISTS (
SELECT * FROM dbo.OperatorOption
WHERE OperatorID = #OperatorID
)
It does not matter you are inserting values as variables. It thinks there is nothing to insert.
You need to produce data that does not match.
Like this:
DECLARE #OperatorID INT = 3, #CurrentCalendarView VARCHAR(50) = 'month';
declare #t table (operatorID int, CurrentCalendarView varchar(50));
insert into #t values (2, 'year');
MERGE #t AS TARGET
USING (SELECT #OperatorID, #CurrentCalendarView) AS source (operatorID, CurrentCalendarView)
on (TARGET.operatorID = Source.operatorID)
WHEN MATCHED THEN
UPDATE SET TARGET.CurrentCalendarView = #CurrentCalendarView
WHEN NOT MATCHED BY TARGET THEN
INSERT (OperatorID, CurrentCalendarView)
VALUES (source.OperatorID, source.CurrentCalendarView);
select * from #t
Insert probably isn't working because your source CTE does not produce any rows. Depending on how your table is organised, you might need to select from some other source, or use table valued constructor to produce source data.

SQL Creating a function which checks variables to make a total

I've made 2 views which calculates the profit per reservation.
One calculates the profit from bikes and the other one from accessories.
Now when I tried SUMing them together, I get false reports. I found out why: something a reservation doesnt contain a bike or a accessory. This field gives a NULL return, which makes my SUM function unusable, because it lacks results.
I tried this:
USE Biker
GO
CREATE FUNCTION fnMaxOmzet
(
#Fiets AS int,
#Accessoire AS int
)
RETURNS int
AS
BEGIN
DECLARE #MaxOmzet AS int
IF #Fiets = NULL
SET #MaxOmzet = #Accessoire
ELSE IF #Accessoire = NULL
SET #MaxOmzet = #Fiets
ELSE
SET #MaxOmzet = #Fiets + #Accessoire
RETURN #MaxOmzet
END
But it isn't working because it gives multiple results..
Probably cause I am using '=' while it checking a list.
Does anyone know a way to make this function?
SELECT * FROM dbo.vAccessoireOmzet
SELECT * FROM dbo.vFietsOmzet
https://ibb.co/bTmJ26
Expected result: List of ID 1 - 100 and the total of AccesoireOmzet + FietsOmzet
Personally, I would use an inline Table Function. You'll find the performance is significantly faster.
NExt, you don't test for the value NULL by using the = operator, you use IS NULL.
This should cater for the logic you have above, however it is untested due to missing DDL and sample data:
CREATE FUNCTION dbo.fnMaxOmzet (#Fiets int, #Accessoire int)
RETURNS TABLE AS
RETURN
(
SELECT CASE WHEN #Fiets IS NULL THEN #Accessoire
WHEN #Accessoire IS NULL THEN #Fiets
ELSE #Fiets + #Accessoire
END AS MaxOmzet
)
GO
OK, just seen your comment with this sql: SELECT dbo.fnMaxOmzet((SELECT FietsOmzet FROM dbo.vFietsOmzet), (SELECT AccessoireOmzet FROM dbo.vAccessoireOmzet)).
That syntax is just wrong, sorry. You need to use APPLY and a JOIN. This is pure guess work as we have no DDL and Sample data... however:
SELECT MO.MaxOmzet--, --**Your other columns go here**
FROM vFietsOmzet FO
JOIN vAccessoireOmzet AO ON --**Your JOIN criteria goes here**
CROSS APPLY dbo.fnMaxOmzet (FO.FietsOmzet, AO.AccessoireOmzet) MO;
You need to use IS NULL rather than = NULL.
But you could also use something like this:
USE Biker
GO
CREATE FUNCTION fnMaxOmzet
(
#Fiets AS int,
#Accessoire AS int
)
RETURNS int
AS
BEGIN
RETURN ISNULL(#Fiets, 0) + ISNULL(#Accessoire, 0)
END
You can read here for more information on the behaviour of = NULL.
Update:
I imagine what you might be looking for is something like:
SELECT
ISNULL(F.Huurovereenkomst_id, A.Huurovereenkomst_id) Huurovereenkomst_id
, SUM(dbo.fnMaxOmzet(F.FietsOmzet, A.AccessoireOmzet)) MaxOmzet
FROM
dbo.vFietsOmzet F
FULL JOIN dbo.vAccessoireOmzet A ON F.Huurovereenkomst_id = A.Huurovereenkomst_id
GROUP BY ISNULL(F.Huurovereenkomst_id, A.Huurovereenkomst_id)
use coalesce thats position
USE Biker
GO
CREATE FUNCTION fnMaxOmzet
(
#Fiets AS int,
#Accessoire AS int
)
RETURNS int
AS
BEGIN
RETURN coalesce(#Fiets+#Accessoire,#Fiets,#Accessoire) from MyTableVar;
END

Must Declare Scalar

I have three separate table variables in my Function,
1 of them is not giving me any errors, the other two are,
I haven't found anything Different Syntax-wise between them, but maybe I need more caffeine.
the error I am receiving is
Must declare the scalar variable "#DispoTable".
DECLARE #CIDdisp INT
DECLARE #DispoTable TABLE
(
CaseID INT,
Code INT,
Description VARCHAR(150)
)
--Gather Data From filter
SELECT #CIDdisp = CaseID, #Code = Code, #Description = Description
FROM fnRecidFilter3(#CaseID,01,01)
-- Insert into Temp table
INSERT INTO #DispoTable (CaseID, Code, Description)
VALUES (#CIDdisp, #Code, #Description)
-- Merge the Temp Table with RecidReport Table
INSERT INTO RecidReport(Code, Description)
SELECT Code, Description
FROM #DispoTable
WHERE (#DispoTable.CaseID) = CaseID
is there something that I am missing?
You can't say:
WHERE (#DispoTable.CaseID) = CaseID
Instead you need to use an alias:
FROM #DispoTable AS d
WHERE d.CaseID = CaseID
But this clause makes no sense anyway. Did you mean to use a variable here? Perhaps:
FROM #DispoTable AS d
WHERE d.CaseID = #CIDdisp
?