SQL Server:An expression of non-boolean type specified in a context where a condition is expected - sql

I apologize I'm asking this question when this specific error type has already been asked multiple times before, but I've looked through them and am not explicitly seeing my answer.
I am trying to build a trigger that takes records inserted into a table (FDC_Trip_History), selects some information from the record, joins on other tables to pull additional data, etc. and inserts a record into another table (Staging).
I'm getting this error at the bottom of my script, the 4th line from the end after the FROM section. Any idea why?
CREATE TRIGGER Insert_Trip_History ON FDC_Trip_History
AFTER INSERT
AS BEGIN
SET NOCOUNT ON;
--If inserted record reaches a certain 'status' of archive then continue
If EXISTS (SELECT * FROM inserted WHERE inserted.description like '%archive%')
BEGIN
--If inserted record can be 'billed', and hasn't already been processed, then continue.
IF EXISTS ( SELECT * FROM inserted
INNER JOIN FDC_Trips on inserted.tdate = FDC_Trips.tdate and inserted.job = FDC_Trips.job and inserted.SourceDB = FDC_trips.sourceDB
INNER JOIN AMS.dbo.Billable_Outcome_Filter as eBill on FDC_trips.SourceDB = eBill.SourceDB and FDC_Trips.outcome = eBill.Outcome_Code)
AND NOT EXISTS ( SELECT * FROM inserted
INNER JOIN Staging as Stg on inserted.tdate = Stg.tdate and inserted.job = Stg.job and inserted.sourcedb = Stg.sourceDB)
BEGIN
INSERT INTO Staging
(EVENT_OPERATION,
EVENT_SOURCE_TABLE,
EVENT_PRIORITY,
EVENT_TIME_UPDATED,
EVENT_STATUS,
EVENT_COMMENT,
TDATE,
JOB,
SOURCEDB,
CUSTNO,
SHIFTNO,
TYPE,
PROFITCENTER,
BILLINGRATEPROFITCENTER)
SELECT
'CREATE' as [EVENT_OPERATION],
'FDC_Trip_History' as [EVENT_SOURCE_TABLE],
'1' as [EVENT_PRIORITY],
GETDATE() as [EVENT_TIME_ADDED],
null as [EVENT_TIME_UPDATED],
'0' as [EVENT_STATUS],
'' as [EVENT_COMMENT],
eTHistory.tdate as [TDATE],
eTHistory.job as [JOB],
eTHistory.sourcedb as [SOURCEDB],
eT.custno as [CUSTNO],
eT.shiftno as [SHIFTNO],
'Completed' as [TYPE],
--Decide Profit Center. Profit center (PC) determined from dispatch zone (Trips.dzone)
CASE
WHEN cType.descr LIKE 'ATS%'
THEN DispatchZone.ATS_ProfitCenter
ELSE DispatchZone.ProfitCenter
END,
--Decide Billing rate profit center. Billing rate profit center (BRPC) determined from pickup zone. Does ATS logic apply to BRPC too?
CASE
WHEN cType.descr LIKE 'ATS%'
THEN PickupZone.ATS_ProfitCenter
ELSE PickupZone.ProfitCenter
END
as [BILLINGRATEPROFITCENTER]
FROM inserted
INNER JOIN FDC_Trip_History as eTHistory
INNER JOIN FDC_Trips as eT on eTHistory.tdate = eT.tdate and eTHistory.job = eT.job and eTHistory.sourcedb = eT.sourcedb
LEFT JOIN Trips as T on T.tdate = eTHistory.tdate and T.sourcedb = eTHistory.sourceDB and T.Job = eTHistory.Job
LEFT JOIN Call_Types as cType on cType.code = eT.calltype and cType.sourceDB = eT.sourceDB
LEFT JOIN Zones as DispatchZone on DispatchZone.code = T.dzone
LEFT JOIN Zones as PickupZone on PickupZone.code = eT.puzone /* Error pops up right here */
END
END
END

You seem to have forgotton the specify the join criteria for the FDC_Trip_History table (the first INNER JOIN).
In addition, you have 14 columns in your INSERT list but 15 in your SELECT statement.

Related

Trigger failure AFTER UPDATE on MariaDB

I am trying to automate some tasks within a DB rather than in the app. We have a small MariaDB for tickets to be sold. When a ticket is sold, its status needs to be set to NOT_VALID until payment is made. After payment is made, the ticket needs to be set to VALID. The invoice itself is in a table 'som_accounting' and with a reference table (som_accountingtickets - because of lazy design decisions) it points to the tickets. Now I am trying to automate that the flag in the ticket table is set to VALID when the PAYMENTSTATUS column in the accounting table changes from OPEN (1) to PAYED (3).
When I use this on the console (dbeaver or terminal) it works fine:
UPDATE som_ticket SET ID_ticketstatus = 4, activation_date = CURRENT_DATE()
WHERE ticketID IN
(SELECT act.ID_ticket FROM som_accountingticket act
INNER JOIN (SELECT * FROM som_accounting) AS ac
ON ac.accountingID = act.ID_accounting
INNER JOIN (SELECT * FROM som_ticket) AS t2
ON t2.ticketID = act.ID_ticket AND t2.ID_ticketstatus = '1'
WHERE act.ID_accounting = '565');
Now I put this into a trigger an I got an error:
CREATE DEFINER=`<user>`#`%` TRIGGER `somt_au_accounting`
AFTER UPDATE
ON `som_accounting`
FOR EACH ROW BEGIN
IF NEW.ID_paymentstatus = 3 AND OLD.ID_paymentstatus = 1 THEN
UPDATE som_ticket SET ID_ticketstatus = '4',
activation_date = CURRENT_DATE()
WHERE ticketID IN
(SELECT act.ID_ticket FROM som_accountingticket act
INNER JOIN (SELECT * FROM som_accounting) AS ac
ON ac.accountingID = act.ID_accounting
INNER JOIN (SELECT * FROM som_ticket) AS t2
ON t2.ticketID = act.ID_ticket
AND t2.ID_ticketstatus = '1'
WHERE act.ID_accounting = OLD.accountingID);
END IF;
END
Database reports this:
Error synchronizing data with database
Reason:
SQL-Fehler [08]: (conn:3) Could not read resultset: unexpected end of stream, read 0 bytes from 4
Query is: UPDATE d0294220.som_accounting
SET ID_paymentstatus=?
WHERE accountingID=?, parameters [3,568]
Why did it run well in the console but not in the trigger?
MariaDB 10.5.8

Temp table throws invalid object name after adding 'SET SHOWPLAN_ALL' Sql Server MS17

I'm fairly new to SQL Server and I've been assigned the task of optimizing some SQL Queries generated by a CMS. After I add the code
SET SHOWPLAN_ALL ON
GO;
and execute the query, the local temp table #tempSecondLevel throws an 'invalid object name' exception in my INSERT INTO statement. You will see a SELECT INTO #tmpSecondLevel statement and then an INSERT INTO #tmpSecondLevel statement. The next statements are for #tmpFirstLevel, and I'm not sure if those are relevant to this question.
use Kentico8_2;
go
set showplan_all on;
go
-- Write revised query here.
DECLARE #ProductNodeGuid uniqueidentifier = '6F6F733D-AE4F-47DC-9BE9-52B967E9F41D'
IF OBJECT_ID('tempdb..#tmpSecondLevel') IS NOT NULL
DROP TABLE #tmpSecondLevel
IF OBJECT_ID('tempdb..#tmpFirstLevel') IS NOT NULL
DROP TABLE #tmpFirstLevel
-- Get all of the items(that go on the secondLevel) that go underneath a heading(on the firstLevel)
-- Get all of the materials that belong to this node that go on the second level
SELECT
NodeLevel = 1
,NodeParentID = CASE WHEN MaterialTypeSelectByMaterial = 0 THEN M.NodeID ELSE M.NodeParentID END
,M.NodeID
,M.MaterialName
,MaterialImage = MV.MaterialVariantImage
,M.NodeAliasPath
,M.Published
,M.NodeGUID
,M.ClassName
,M.NodeOrder
INTO
#tmpSecondLevel
FROM
View_NOF_Material_Joined M
JOIN View_NOF_Product_Joined P
ON P.ProductMaterialNodeGuidList LIKE '%' + CONVERT(nvarchar(36), M.NodeGUID) + '%'
JOIN View_NOF_MaterialType_Joined MT
ON MT.NodeID = M.NodeParentID
LEFT JOIN View_NOF_MaterialVariant_Joined MV
ON MV.NodeParentID = M.NodeID AND MV.NodeOrder = 1 -- always the first
WHERE
P.NodeGUID = #ProductNodeGuid AND MaterialTypeSelectByMaterial = 1
-- Get all of the material variants that belong to this node that go on the second level
INSERT INTO
#tmpSecondLevel
SELECT
NodeLevel = 1
,NodeParentID = CASE WHEN MaterialTypeSelectByMaterial = 0 THEN M.NodeID ELSE M.NodeParentID END
,MV.NodeID
,MaterialName = MV.MaterialVariantName
,MaterialImage = MV.MaterialVariantImage
,MV.NodeAliasPath
,MV.Published
,MV.NodeGUID
,MV.ClassName
,MV.NodeOrder
FROM
View_NOF_MaterialVariant_Joined MV
JOIN View_NOF_Product_Joined P
ON P.ProductMaterialNodeGuidList LIKE '%' + CONVERT(nvarchar(36), MV.NodeGUID) + '%'
JOIN View_NOF_Material_Joined M
ON M.NodeID = MV.NodeParentID
JOIN View_NOF_MaterialType_Joined MT
ON MT.NodeID = M.NodeParentID
WHERE
P.NodeGUID = #ProductNodeGuid
AND MaterialTypeSelectByMaterial = 0
-- Get all of the headings( for the firstLevel) that go above a list of items(on the secondLevel)
-- Get all of the material types that are used as headings
SELECT DISTINCT
NodeLevel = 0
,NodeParentID = NULL
,MT.NodeID
,MaterialName = MT.MaterialTypeName
,MaterialImage = ''
,MT.NodeAliasPath
,MT.Published
,MT.NodeGUID
,MT.ClassName
,MT.NodeOrder
INTO
#tmpFirstLevel
FROM
View_NOF_MaterialType_Joined MT
INNER JOIN #tmpSecondLevel M
ON MT.NodeID = M.NodeParentID
-- Get all of the materials that are used as headings
INSERT INTO
#tmpFirstLevel
SELECT DISTINCT
NodeLevel = 0
,NodeParentID = NULL
,MJ.NodeID
,MaterialName = MJ.MaterialName
,MaterialImage = ''
,MJ.NodeAliasPath
,MJ.Published
,MJ.NodeGUID
,MJ.ClassName
,MTJ.NodeOrder
FROM
View_NOF_Material_Joined MJ
INNER JOIN View_NOF_MaterialType_Joined MTJ
ON MTJ.NodeID = MJ.NodeParentID
INNER JOIN #tmpSecondLevel M
ON MJ.NodeID = M.NodeParentID
-- Put all of the second level items (the details) and first level items (the headings) in the same table
SELECT * FROM #tmpSecondLevel
UNION
SELECT * FROM #tmpFirstLevel
ORDER BY NodeOrder
IF OBJECT_ID('tempdb..#tmpSecondLevel') IS NOT NULL
DROP TABLE #tmpSecondLevel
IF OBJECT_ID('tempdb..#tmpFirstLevel') IS NOT NULL
DROP TABLE #tmpFirstLevel
I predict this is a simple question to ask since I only added two lines of code, but the help is much appreciated. If you have any tips for me about optimizing these queries, that is greatly appreciated as well.
Thanks in advance.
You are getting the error because SET SHOWPLAN_ALL is the command to show Estimated execution plans. Therefore no TSQL commands are actually executed, and thus the #tmpSecondLevel table is never created. So you get an error. This would be the same thing as clicking the "Display Estimated Execution Plan" in SSMS.
You can read about that command here: https://learn.microsoft.com/en-us/sql/t-sql/statements/set-showplan-all-transact-sql
If you want to show the Actual execution replace SHOWPLAN_ALL line with SET STATISTICS XML ON. This will display the actual execution plan when you run the query.

SQL Statement Needed - results from a range but not within another range

I have two tables.
A MEMBERS table that lists all of the details about a member and
a second table that stores a historical record of all of the changes to each column
in the MEMBERS table. For example, if a member's status changed from Active to Frozen on June 1, the MEMBERCHANGES tables would have an entry stating that change.
I need to create a SQL Statement that lists all of the MEMBER records that are in a status of Freeze, who changed to the status in a date range but that there aren't any changes in a second date range.
For example, I need all member who changed to a status of FREEZE between Jan 1 and May 1 but who haven't had any changes to the status field from May 2 through Aug 31.
SELECT MEMBERS.scancode
,MEMBERS.fname
,MEMBERS.lname
,MEMBERTYPES.description
,MEMBERS.STATUS
,MEMBERS.email
,MEMBERS.datejoin
,MEMBERS.dateexpire
,MEMBERS.daterenewal
,MEMBERCHANGES.datechange
,MEMBERCHANGES.newvalue
FROM MEMBERS
INNER JOIN MEMBERCHANGES ON MEMBERS.memid = MEMBERCHANGES.memid
INNER JOIN MEMBERTYPES ON MEMBERS.mtypeid = MEMBERTYPES.mtypeid
AND NOT EXISTS (
SELECT MEMBERS.memid
FROM MEMBERS AS MEM2
INNER JOIN MEMBERCHANGES ON MEM2.memid = MEMBERCHANGES.memid
INNER JOIN MEMBERTYPES ON MEM2.mtypeid = MEMBERTYPES.mtypeid
WHERE (MEMBERCHANGES.columnname = 'status')
AND (MEMBERCHANGES.newvalue = 'F')
AND (
MEMBERCHANGES.datechange BETWEEN '2015-05-02'
AND '2015-08-31'
)
AND (MEM2.STATUS = 'F')
)
WHERE (MEMBERCHANGES.columnname = 'status')
AND (
MEMBERCHANGES.datechange BETWEEN '2015-01-01'
AND '2015-05-01'
)
AND (MEMBERS.STATUS = 'F')
AND (MEMBERCHANGES.newvalue = 'F')
I cleaned up your query with aliases and removed some things I think were redundant. Forgive me for changing to lowercase as well.
select ...
from
MEMBERS m
inner join MEMBERCHANGES on mc.memid = m.memid
inner join MEMBERTYPES on mt.mtypeid = m.mtypeid
where
/* current status is Freeze */
m.STATUS = 'F'
/* changed to Freeze between certain dates */
and mc.columnname = 'status'
and mc.datechange between '2015-01-01' and '2015-05-01'
and mc.newvalue = 'F'
/* and no changes between later dates */
and not exist (
select 1
from MEMBERCHANGES mc2
where
mc2.memid = mc.memid
and mc2.columnname = 'status'
and mc2.datechange between '2015-05-02' and '2015-08-31'
and mc2.newvalue = 'F'
)
Since current date is well past August 31 I'm wondering if you'll have a problem checking against the current status which could have changed in the last month and a half. I trust that you know the data you're dealing with.
It's also certainly possible that the status could have changed to Freeze during the first window but later changed to something else during the same window. And then its current status could be Freeze because of a change between September 1 and present date. I don't know if you need to check for that kind of thing but this query may not guarantee anything about the member status at the end of May 1st.

Using query results in further procedcures

I'm fairly new to SQL especially PL/SQL, I have a grasp of the basics but what i'm trying to do goes over my head. This is a small part of a larger system but I will focus on 3 tables Sale_Head, Sale_Line and Product. This work is being done in Orcale SQL developer.
http://imgur.com/OrfhM0g,i4pMnTx - Sale Table
http://imgur.com/OrfhM0g,i4pMnTx#1 - Product Table
(Im a newbie so i dont have enough rep to directly post images)
Im attempting to build up some procedures that process pending sales. Sales have a status in the Sale_Head which can either be p(pending), s(shipped), i(in progress), x(cancelled), or b(back orders). The procedure(s) need to find sales with a pending status (i've got that far in my code), then check the products stock levels are above the minimum level enough to complete the sale. If all these conditions are met pending sales become i (in progress) and if there is inadequate stock it comes backordered (b). I have a general idea of how to go about this, but when it comes having to referencing the product table using the foreign from sale_line I get confused.
--create or replace procedure Process_Products is
--begin
select Sale_Head.Sale_Num , Sale_Line.Product_Code as
from Sale_Head
inner join Sale_Line on
Sale_Head.Sale_Num = Sale_Line.SALE_NUM
where Sale_head.Status = 'P';
--if Sale_Line.Product_Code = Product.Product_Code >
--end;
This returns the product codes for orders that have a pending status, but now I need to check their stock levels in the product table and make adjustments.
Please correct me if I am wrong, but if you are saying "for those sales in a pending status where enough inventory exists to fulfill the order, change the status to i (in progress), otherwise not enough inventory exists, so change the status to b (backordered)", then the following should help:
-- This is a useful query to display what you need - debugging, use in cursor, etc
SELECT sh.Sale_Num, sl.Product_Code, sl.Quantity as QtyToBuy,
p.Stock_Count, p.Minimum_Level,
(Case When sl.Quantity <= p.Minimum_Level Then 'i'
Else 'b' end) as NewStatus
FROM Sale_Head sh
INNER JOIN Sale_Line sl
ON sh.Sale_Num = sl.SALE_NUM
INNER JOIN Product p
ON sl.Product_Code
WHERE Sale_head.Status = 'P';
The status code can be updated in one query if that is what you want:
--This query will actully do the update (if view is updatable)
UPDATE
(
SELECT sh.Status, (Case When sl.Quantity <= p.Minimum_Level Then 'i'
Else 'b' end) as NewStatus
FROM Sale_Head sh
INNER JOIN Sale_Line sl
ON sh.Sale_Num = sl.SALE_NUM
INNER JOIN Product p
ON sl.Product_Code
WHERE sh.Status = 'P'
) a
SET a.Status = a.NewStatus;
If the above view is not updatable, try this syntax:
--Otherwise try this syntax
UPDATE Sale_Head sh1 Set Sale_Head.Status =
SELECT (Case When sl.Quantity <= p.Minimum_Level Then 'i'
Else 'b' end) as NewStatus
FROM Sale_Head sh
INNER JOIN Sale_Line sl
ON sh.Sale_Num = sl.SALE_NUM
INNER JOIN Product p
ON sl.Product_Code
WHERE sh1.Sale_Num = sh.Sale_Num
)
WHERE Sale_Head.Status = 'P';

sql query updates all rows and not only where clause

I am having trouble executing this query:
update public.fortune_companies
set industry_id = (select id
from public.industries
where name = 'Agriculture, Forestry and Fishing')
from Temp_Sic_Fortune_Companies as temp
left join public.fortune_companies as fc on fc.account_name = temp.account_name
where temp.sic between '0' and '499';
I think this is supposed to set the industry_id for only ones that have a sic number of 0-499 but it actually sets every record to the same id. No matter if the sic number is between 0-499 or not.
Why is this.
DECLARE #id INT;
SELECT #id = id
FROM public.industries
WHERE name = 'Agriculture, Forestry and Fishing';
UPDATE fc
SET industry_id = #id
FROM public.fortune_companies AS fc
WHERE EXISTS
(
SELECT 1
FROM dbo.Temp_Sic_Fortune_Companies
WHERE account_name = fc.account_name
AND sic BETWEEN '0' and '499'
);
Of course, if temp.sic = '3000', it will be part of the set. This is one of the dangers of using the wrong data type (or the wrong operator). You can fix that by saying:
AND sic BETWEEN '0' and '499'
AND LEN(sic) <= 3
Or by saying:
AND CASE WHEN ISNUMERIC(sic) = 1 THEN
CONVERT(INT, sic) ELSE -1 END BETWEEN 0 AND 499
(This avoids errors if - since you've let them - someone enters a non-numeric value into the column.)
Or by using the right data type in the first place.
Change the left join to inner join