What do these trigger errors mean - sql

Hey Guys thanks for the help earlier. I have now ran into a new problem. A few steps later in my homework I needed to add an additional part to this trigger. The trigger needs to subtract one from the number of copies. When the number of copies hits 0 it should display unavailable. I have been trying for the last few hours to figure it out and this is what I came up with. Any help or suggestions would be greatly appreciated!!
CREATE or REPLACE Trigger Unavailable_Rule
BEFORE INSERT ON Transaction
FOR EACH ROW
BEGIN
IF :new.Date_Rented_Out is not null AND :new.Date_Returned is NULL AND Num_Copies=1
THEN
UPDATE Video
set Num_Copies = Num_Copies - 1,
Status = 'Unavailable'
where Vid_Num = :new.Vid_Num;
ELSE
Num_Copies = Num_Copies - 1;
End IF;
END;
/
show errors;
6/4 PL/SQL: SQL Statement ignored
7/15 PL/SQL: ORA-00971: missing SET keyword
13/13 PLS-00103: Encountered the symbol "=" when expecting one of the f ollowing: := . ( # % ;
14/2 PLS-00103: Encountered the symbol "END"

Your update statement is misformed. Instead of:
UPDATE Video
Num_Copies = Num_Copies -1
set Status = 'Unavailable'
where Vid_Num = :new.Vid_Num;
Assign Num_Copies in a set:
UPDATE Video
set Num_Copies = Num_Copies - 1,
Status = 'Unavailable'
where Vid_Num = :new.Vid_Num;
EDIT:
Your if statement can be replaced with:
UPDATE Video
set Num_Copies = Num_Copies - 1,
Status = (case when :new.Date_Rented_Out is not null AND :new.Date_Returned is NULL AND Num_Copies = 1 then 'Unavailable'
else status
end)
where Vid_Num = :new.Vid_Num;

Related

Update one column only when any other column change

I am trying to create an update statement on SQL Server to set one of the cards as default and all the others as not, however, if I have 3 cards and card 1 set to default and now I want to set card 2 as default I get all 3 cards set as updated, when I should only set cards 1 and 2. I am currently using the following query:
UPDATE Card
SET
ModifiedDateTimeUtc = #ModifiedDateTimeUtc,
IsDefault = CASE WHEN Id = #CardId THEN 1 ELSE 0 END
WHERE CustomerId = #CustomerId;
I need to modify this query so only the cards with values updated get to set a new modified date/time.
PS, I cannot use triggers on this database (unfortunately) so I need to find a solution using a "simple" SQL statement.
Maybe it could be write in other ways but you can do like this:
UPDATE Card
SET
ModifiedDateTimeUtc =
CASE WHEN Id = #CardId THEN
CASE WHEN IsDefault = 1 THEN ModifiedDateTimeUtc ELSE #ModifiedDateTimeUtc END
ELSE
CASE WHEN IsDefault = 0 THEN ModifiedDateTimeUtc ELSE #ModifiedDateTimeUtc END
END,
IsDefault = CASE WHEN Id = #CardId THEN 1 ELSE 0 END
WHERE CustomerId = #CustomerId;
What should do this?
If the Id is the same with the parameter and the old value, before update, is 1, datetime will be the same, no update will be made, else (means old value = 0) then it will be updated. And the same for old value= 0...
Is this what you want?
UPDATE Card
SET ModifiedDateTimeUtc = #ModifiedDateTimeUtc,
IsDefault = (CASE WHEN Id = #CardId THEN 1 ELSE 0 END)
WHERE CustomerId = #CustomerId AND
IsDefault <> (CASE WHEN Id = #CardId THEN 1 ELSE 0 END);
Usually, I wouldn't repeat a CASE expression in the WHERE. In this case, though, this is the new value for the column, so I think it is a clean expression of the logic.

PLSQL syntax error near ";"

I am trying to run a query for liquibase update and I have a PLSQL block in there, the block has over 500 lines so I only post a few lines where the error is happening for now.
BEGIN
IF NOT EXISTS(select 1 from "public"."eod_report" where "id" = NEW."id") THEN
-- LOADING STRUCTURE SECTION
select "id" into NEW.organization_unit_id from organization_unit where site_id = NEW.organization_unit_id;
orgUnitId := CAST(NEW.organization_unit_id as int8);
--INSERT
IF (NEW.transactions_count is NULL) THEN
NEW.transactions_count := 0;
END IF;
IF (NEW.total_sales is NULL) THEN
NEW.total_sales := 0;
END IF;
INSERT INTO "public"."eod_report"("id",batch,total_sales,transactions_count,organization_unit_id,pos_total_sales,pos_transactions_count,pos_total_points,total_points,transaction_date)
VALUES (NEW."id",NEW.batch,NEW.total_sales,NEW.transactions_count,orgUnitId,NEW.pos_total_sales,NEW.pos_transactions_count,NEW.pos_total_points,NEW.total_points,NEW.transaction_date);
-- updates delay transaction or each batch
select max(id) into lastEodId from "public"."transaction" where transaction_type = 4 and org_unit_id = orgUnitId and id &lt ;NEW."id";
for eodRow IN
select count(case when transaction_type = 3 then -1 else 1 end) as trCount,sum(case when report_prefix = true then points else -points end) as ptSum,sum(case when report_prefix = true then amount else -amount end) as trSum, batch as trBatch from "public"."transaction"
where id &gt ;lastEodId and id &lt ;NEW."id" and report_prefix is not null and org_unit_id = orgUnitId
and batch &lt ;NEW.batch group by batch
LOOP
UPDATE "public"."eod_report" SET delayed_points =
(delayed_points + eodRow.ptSum),former_delayed_sales =
END LOOP;
END IF;
RETURN NULL;
And I am getting this error when I try to execute the query:
ERROR:
syntax error at or near ";"
LINE 453: ..._type = 4 and org_unit_id = orgUnitId and id &lt ;NEW."id";
^
SQL state: 42601
Character: 15018
there is a screenshot where the error is highlighted
Looks like the < and > chars are replaced with &lt ; so the syntax is incorrect.
fix the SQL by replacing all &lt ; with < to have
... org_unit_id = orgUnitId and id < NEW."id";
Also &gt ; must be replaced with >
It could happens e.g. because of URL encoding of text sent from UI (browser)
You find the same problem in multiple parts of your query, because HTML entities like "&lt ;" and "&gt ;" are not legal in an SQL query, which the error points to. You should change them to "<" and ">" accordingly.

SQL Developer bind variables prompt: force string values

I'm trying to use SQL Developer bind variables prompt to speed up query execution, but I'm not getting the desired output: looks like the values I put in get converted in number.
Table description:
Nome Null Type
------------------ -------- ------------
NUM NOT NULL VARCHAR2(13)
IS_OK NUMBER(1)
initial situation:
select NUM, IS_OK from numbers_table where NUM = cast(:dn as varchar2(13));
NUM |IS_OK |
------------|------|
08331930078 |1 |
working updates:
1.
update numbers_table set IS_OK = 0 where NUM = 08331930078;
update numbers_table set IS_OK = 0 where NUM = '08331930078';
ouput:
'1 row updated'
non-working updates:
1.
update numbers_table set IS_OK = 0 where NUM = :dn;
update numbers_table set IS_OK = 0 where NUM = cast(:dn as varchar2(13));
output:
'0 rows updated'
Don't know what else can I do to force the value being parsed as a string.
SQL Developer version 4.1.3.20
That's interesting, and looks like a bug. You don't actually need to cast, the value from the 'enter binds' window is a string anyway, so this works:
update numbers_table set IS_OK = 0 where NUM = :dn;
when the zero-padded string 08331930078 is entered in the dialog.
The cast is not needed but ought to still work. If you run as a script instead, with a defined bind variable, then both forms do work:
var dn varchar2(13);
exec :dn := '08331930078';
update numbers_table set IS_OK = 0 where NUM = :dn;
rollback;
update numbers_table set IS_OK = 0 where NUM = cast(:dn as varchar2(13));
rollback;
You get 1 row updated for both statements. Going back to running as a statement still prompts and still has the same (odd) behaviour even when the bind variable has been defined in a script in the same session.
Incidentally, when you do:
update numbers_table set IS_OK = 0 where NUM = 08331930078;
what you're actually doing, as you can see form the execution plan's predicate section, is:
update numbers_table set IS_OK = 0 where to_number(NUM) = 8331930078;
which will stop any index on the num column being used, and may result in unexpected results - in this case, if these are e.g. UK phone numbers you probably won't have the same value with and without the leading zero, but it's something to be wary of generally.

Procedure stops when legacy, new error traps are next to each other

We have a bunch of old stored procedures with legacy style error trapping. I changed one the other day and included a newer TRY...CATCH block. The stored procedure just stopped after the TRY/CATCH and returned as though there were an error in the legacy block.
If I put a
SELECT NULL
in between the two everything works fine. Anyone know why this is happening?
--BEGIN NEW ERROR TRAP--
BEGIN TRY
Do stuff...
END TRY
BEGIN CATCH
END CATCH
--END NEW ERROR TRAP---
----------------- OLD SCHOOL TRAP BEGIN -----------------
SELECT #spERROR = ##ERROR ,
#spROWCOUNT = ##ROWCOUNT
SET #spRETURN = #spRETURN + 1
IF ( #spROWCOUNT <= 0
OR #spERROR <> 0
)
SET #spRETURN = 0 - #spRETURN
IF ( #spROWCOUNT <= 0
OR #spERROR <> 0
)
RETURN #spRETURN
SELECT #spROWCOUNT = -1 ,
#spERROR = -1
------------------ OLD SCHOOL ERROR TRAP END ------------------
In your try catch block, the last statement is probably doing something that sets the row count to 0. The "SELECT NULL" is setting the row count to 1, since it returns one row, so no error is detected.
You can fix this by changing the logic in the "old" code or by setting your row count variable in the try/catch code. I would recommend that you remove the SELECT NULL, since it would guarantee success and you may not want that behavior.

CASE expression syntax error SQL

I have researched everywhere but still can't seem to fix a simple error:
Running Microsoft SQL server:
UPDATE copyprogmaster
SET active =
CASE
WHEN active = 1 THEN active = 0
WHEN active = 0 THEN active = 1
ELSE active
END
WHERE source = 'Mass_Mail'
my error is :
Line 4: Incorrect syntax near '='.
Remove the = after the THEN, so:
UPDATE copyprogmaster
SET active =
CASE
WHEN active = 1 THEN 0
WHEN active = 0 THEN 1
ELSE active
END
WHERE source = 'Mass_Mail'
You already have active = after the SET on the second line.
You do not need to repeat "active =" after THEN
UPDATE copyprogmaster
SET active =
CASE
WHEN active = 1 THEN 0
WHEN active = 0 THEN 1
ELSE active
END
WHERE source = 'Mass_Mail'
Here's an example from the documentation at http://msdn.microsoft.com/en-us/library/ms181765.aspx
USE AdventureWorks2008R2;
GO
SELECT ProductNumber, Category =
CASE ProductLine
WHEN 'R' THEN 'Road'
WHEN 'M' THEN 'Mountain'
WHEN 'T' THEN 'Touring'
WHEN 'S' THEN 'Other sale items'
ELSE 'Not for sale'
END,
Name
FROM Production.Product
ORDER BY ProductNumber;
GO
Based on your query, I assume the active field is bit or int (assuming that int field has only values 0, 1, or NULL). In that case, I believe that you can write the query as following:
UPDATE dbo.copyprogmaster
SET active = active ^ 1
WHERE source = 'Mass_Mail'
Notice that the query can handle NULL values and also the rows #1, #4 and #6 in the screenshot are unchanged. Screenshot #1 shows table structure and screenshot #2 displays sample execution of the above query.
Hope that helps.
Screenshot #1:
Screenshot #2: