trigger error:=ORA-04079: invalid trigger specification - sql

trigger error:=ORA-04079: invalid
trigger specification
the code causing that error is below:
CREATE OR REPLACE TRIGGER TRGBILLINGADDRESS
AFTER INSERT OR DELETE OR UPDATE ON TBLMACCOUNTADDRESS
add1 wom.tbltaddress.address1%TYPE;
add2 wom.tbltaddress.address2%TYPE;
cityid wom.tbltaddress.city_id%TYPE;
stateid wom.tbltaddress.state_id%TYPE;
pincd wom.tbltaddress.pincode%TYPE;
BEGIN
SELECT address1,address2,city_id,state_id,pincode
INTO add1,add2,cityid,stateid,pincd FROM wom.tbltaddress ta WHERE ta.ID IN (
SELECT vbac.billing_address_id
FROM wom.vw_billaddresschange vbac, wom.tbltaddress ita
WHERE vbac.billing_address_id = ita.ID
AND vbac.lcid = parlcid);
IF add1 = :NEW.address1 AND add2 = :NEW.address2 AND cityid = :NEW.cityid AND stateid = :NEW.stateid AND pincode = :NEW.zip THEN
dbms_output.put_line('Address Already Exist in tbltaddress table');
ELSE
UPDATE wom.tbltaddress ta
SET ta.address1 = :NEW.address1,
ta.address2 = :NEW.address2,
ta.city_id = :NEW.cityid,
ta.country_id = 'CTR0001',
ta.state_id = :NEW.stateid,
ta.pincode = :NEW.zip
WHERE ta.ID IN (
SELECT vbac.billing_address_id
FROM wom.vw_billaddresschange vbac, wom.tbltaddress ita
WHERE vbac.billing_address_id = ita.ID
AND vbac.lcid = parlcid);
END IF;
END;

You should use DECLARE before declaring your variables.
CREATE OR REPLACE TRIGGER TRGBILLINGADDRESS
AFTER INSERT OR DELETE OR UPDATE ON TBLMACCOUNTADDRESS
DECLARE
add1 wom.tbltaddress.address1%TYPE;
add2 wom.tbltaddress.address2%TYPE;
cityid wom.tbltaddress.city_id%TYPE;
stateid wom.tbltaddress.state_id%TYPE;
pincd wom.tbltaddress.pincode%TYPE;
BEGIN

Related

SQL Stored Procedure Parameter set to Uppercase

I want to force a user's string input in a stored procedure to uppercase. I tried writing UPPER prior to the #parameterName but I got a syntax error. Is this possible? Would be it be better suited to convert the string to uppercase in the statement itself? Here's the code to my SP where I was attempting to use UPPER in the parameter definition.
ALTER PROCEDURE [dbo].[UpdateEntries]
UPPER #ENTRY_TYPE NVARCHAR(20) = '',
UPPER #ENTRY_NAME NVARCHAR(50),
#CLASS_TYPE_ID INT,
#ENTRY_PRICE DEC(4,2),
#ENTRY_DESCRIPT NVARCHAR(max),
#PET_FRIENDLY BIT,
#AGE_RESTRICTION BIT,
#PRICE_RANGE_ID INT,
#RESTAURANT_TYPE_ID INT NULL
AS
BEGIN
SET NOCOUNT ON;
IF #ENTRY_TYPE = 'ACTIVITY'
BEGIN
UPDATE ACTIVITY_DETAIL
SET ACT_NAME = #ENTRY_NAME,
ACT_PRICE = #ENTRY_PRICE,
ACT_DESCRIPT = #ENTRY_DESCRIPT,
ACT_DOG_FRIENDLY = #PET_FRIENDLY,
ACT_AGE_RESTRICTION = #AGE_RESTRICTION,
ACT_PRICE_RANGE_ID = #PRICE_RANGE_ID
WHERE NOT EXISTS (SELECT 1 FROM dbo.[ACTIVITY_DETAIL] WHERE ACT_NAME = #ENTRY_NAME);
END
IF #ENTRY_TYPE = 'BUSINESS'
BEGIN
UPDATE BUSINESS_DETAIL
SET BUSINESS_NAME = #ENTRY_NAME,
BUSINESS_PRICE = #ENTRY_PRICE,
BUSINESS_DESCRIPT = #ENTRY_DESCRIPT,
BUSINESS_DOG_FRIENDLY = #PET_FRIENDLY,
BUSINESS_PRICE_RANGE_ID = #PRICE_RANGE_ID
WHERE NOT EXISTS (SELECT 1 FROM dbo.[BUSINESS_DETAIL] WHERE BUSINESS_NAME = #ENTRY_NAME);
END
IF #ENTRY_TYPE = 'HOTEL'
BEGIN
UPDATE HOTEL_DETAIL
SET HOTEL_NAME = #ENTRY_NAME,
HOTEL_PRICE = #ENTRY_PRICE,
HOTEL_DESCRIPT = #ENTRY_DESCRIPT,
HOTEL_PET_FRIENDLY = #PET_FRIENDLY,
HOTEL_PRICE_RANGE_ID = #PRICE_RANGE_ID
WHERE NOT EXISTS (SELECT 1 FROM dbo.[HOTEL_DETAIL] WHERE HOTEL_NAME = #ENTRY_NAME);
END
IF #ENTRY_TYPE = 'RESTAURANT'
BEGIN
UPDATE RESTAURANT_DETAIL
SET RESTAURANT_NAME = #ENTRY_NAME,
RESTAURANT_PRICE_AVG = #ENTRY_PRICE,
RESTAURANT_DESCRIPT = #ENTRY_DESCRIPT,
RESTAURANT_DOG_FRIENDLY = #PET_FRIENDLY,
RESTAURANT_PRICE_RANGE_ID = #PRICE_RANGE_ID
WHERE NOT EXISTS (SELECT 1 FROM dbo.[RESTAURANT_DETAIL] WHERE RESTAURANT_NAME = #ENTRY_NAME);
END
END
UPPER #ENTRY_TYPE NVARCHAR(20) = '',
UPPER #ENTRY_NAME NVARCHAR(50),
These are wrong. No such usage.
#ENTRY_TYPE NVARCHAR(20) = '',
#ENTRY_NAME NVARCHAR(50),
SELECT #ENTRY_TYPE = UPPER(#ENTRY_TYPE);
SELECT #ENTRY_NAME = UPPER(#ENTITY_NAME);

Stored procedure (SQL Server), can't find the issue

This stored procedure is use for searching records.
When I only fill in the parameter #ID or #FirstName, it works. But not if I only fill in #LastName.
For example:
#ID = 1, the rest is NULL --> should give 1 row --> RESULT: 1 row (ok)
#ID = NULL, #FirstName = 'Tim', the rest is NULL --> should give 1 row --> RESULT: 1 row (ok)
#ID = NULL, #FirstName = NULL, #LastName = 'BlaBla', the rest is NULL
--> should give 1 row --> RESULT: all rows (Not OK)
Anyone know why?
Thanks in advance.
This is my procedure:
ALTER PROCEDURE lookupSubscriber
-- Add the parameters for the stored procedure here
#ID int,
#firstname nvarchar(50),
#lastname nvarchar(60),
#street nvarchar(80),
#housenumber nvarchar(6),
#companyname nvarchar(50),
#city nvarchar(50),
#ResultString nvarchar(80) OUTPUT,
#ResultValue int OUTPUT,
#ResultCount int OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--Replacing empty strings with NULL
IF #ID = 0 BEGIN SET #ID = NULL; END
IF #firstname = '' BEGIN SET #firstname = NULL; END
IF #lastname = '' BEGIN SET #lastname = NULL; END
IF #street = '' BEGIN SET #street = NULL; END
IF #companyname = '' BEGIN SET #companyname = NULL; END
IF #housenumber = '' BEGIN SET #housenumber = NULL; END
IF #city = '' BEGIN SET #city = NULL; END
-- Insert statements for procedure here
BEGIN TRY
SELECT s.ID, COALESCE(d.FirstName,'NONE'), COALESCE(d.LastName,'NONE'), d.Street, COALESCE(d.CompanyName,'NONE'), d.HouseNumber, c.name
FROM Subscriber s
INNER JOIN SubscriberDetail d ON d.ID = s.Detail_ID
INNER JOIN City c ON d.City_ID = c.ID
WHERE (s.ID = COALESCE(#ID, s.ID)
AND d.FirstName = COALESCE(#firstname, d.FirstName) OR d.FirstName = 'NONE'
AND d.LastName = COALESCE(#lastname, d.LastName) OR d.LastName = 'NONE'
AND d.Street = COALESCE(#street, d.Street)
AND d.CompanyName = COALESCE(#companyname, d.CompanyName) OR d.CompanyName = 'NONE'
AND d.HouseNumber = COALESCE(#housenumber, d.HouseNumber)
AND c.name = COALESCE(#city, c.name))
SET #ResultCount = ##ROWCOUNT
SET #ResultString = 'Lookup successful'
SET #ResultValue = 0
END TRY
BEGIN CATCH
SET #ResultString = 'ERROR: ' + ERROR_MESSAGE()
SET #ResultValue = 2
END CATCH
END
GO
Example data:
Subscriber:
ID = 1 | Type_ID = 1 | Detail_ID = 2
ID = 2 | Type_ID = 2 | Detail_ID = 3
SubscriberDetail:
ID = 1 | FirstName = 'Laurens' | LastName = 'De Neys' | CompanyName = NULL | Street = 'Ergens' | HouseNumber = 2 | City_ID = 1
ID = 2 | FirstName = 'Tim' | LastName = 'Blabla' | CompanyName = NULL | Street = 'Iets' | HouseNumber = 26 | City_ID = 2
City:
ID = 1 | name = 'Liedekerke' | postalCode = 1770
ID = 1 | name = 'Leuven' | postalCode = 3000
Perhaps you need to put your OR conditions in parentheses with your original conditions?
For all of these expressions:
AND d.LastName = COALESCE(#lastname, d.LastName) OR d.LastName = 'NONE'
Change to
AND (d.LastName = COALESCE(#lastname, d.LastName) OR d.LastName = 'NONE')
EDIT
Well, I can't know what is in your DB, but I have a feeling some of that logic is incorrect. Try this:
SELECT s.ID, COALESCE(d.FirstName,'NONE'), COALESCE(d.LastName,'NONE'), d.Street, COALESCE(d.CompanyName,'NONE'), d.HouseNumber, c.name
FROM Subscriber s
INNER JOIN SubscriberDetail d ON d.ID = s.Detail_ID
INNER JOIN City c ON d.City_ID = c.ID
WHERE (#id is null or s.ID = #ID)
AND (#firstname is null or d.FirstName = #firstname)
AND (#lastname is null or d.LastName = #lastname)
AND (#street is null or d.Street = #street)
AND (#companyname is null or d.CompanyName = #companyname)
AND (#housenumber is null or d.HouseNumber = #housenumber)
AND (#city is null or c.name = #city)
Your WHERE statement has its AND and OR conditions arranged in such a way that they are evaluating incorrectly for what I assume you want them to do. You can fix it by encapsulating your OR statments to account for the correct parts. Example:
WHERE (s.ID = COALESCE(#ID, s.ID)
AND (d.FirstName = COALESCE(#firstname, d.FirstName) OR d.FirstName = 'NONE')
AND (d.LastName = COALESCE(#lastname, d.LastName) OR d.LastName = 'NONE')
AND d.Street = COALESCE(#street, d.Street)
AND (d.CompanyName = COALESCE(#companyname, d.CompanyName) OR d.CompanyName = 'NONE')
AND d.HouseNumber = COALESCE(#housenumber, d.HouseNumber)
AND c.name = COALESCE(#city, c.name))
EDIT: Looking at the same data, there's an additional problem here. You're trying to check equality on Company name to COALESCE(#companyname, d.companyname), but you have cases where your CompanyName is NULL. When a value is NULL, it's unknown, so SQL won't treat it as being equal, even to itself.
This is one reason I generally prefer, rather than the COALESCE syntax above to do somethng like this:
AND (#companyname IS NULL OR d.CompanyName = #companyname)
The above doesn't care if the stored value for company name is null if the parameter is also null (and if the parameter isn't null, your equality still works out).

FireBird: How do you nest a select in an if?

I'm very new to FireBird, but I want to know how I can use a select statement as part of my conditional criteria. I feel like I've been to the internet in back trying to find a way to do this, but haven't come up with much. Below is my attempt at getting this to work. Thanks in advance for any help.
SET TERM ^ ;
ALTER PROCEDURE sp_test (
IPADD Varchar(32),
HN Varchar(32),
NOTE Varchar(200) )
RETURNS ( update_count integer )
AS
BEGIN
IF((SELECT COUNT(*)
FROM ADDRESSES a
WHERE a.ADDRESS_TYPE = 'Reserved'
AND a.ALIVE = 'N'
AND (a.HOST_NAME = '' OR a.HOST_NAME is NULL)
AND (a.DNS_NAME = '' OR a.DNS_NAME is NULL)
AND (a.SYSTEM_NAME = '' OR a.SYSTEM_NAME is NULL)) > 0)
THEN
UPDATE
ADDRESSES a
SET
a.HOST_NAME = :HN,
a.ADDRESS_TYPE = 'Assigned',
a.NOTES = :NOTE
WHERE
a.SHORT_IP_ADDRESS = :IPADD;
update_count = 1;
SUSPEND;
ELSE
update_count = 0;
SUSPEND;
END^
SET TERM ; ^
GRANT EXECUTE
ON PROCEDURE sp_test TO SYSDBA;
Using COUNT to check is there records to update is not the best way, use EXISTS instead, ie your IF would be
IF(EXISTS(SELECT 1 FROM ADDRESSES a
WHERE a.ADDRESS_TYPE = 'Reserved'
AND a.ALIVE = 'N'
AND (a.HOST_NAME = '' OR a.HOST_NAME is NULL)
AND (a.DNS_NAME = '' OR a.DNS_NAME is NULL)
AND (a.SYSTEM_NAME = '' OR a.SYSTEM_NAME is NULL)))
THEN
But there seems to be a problem with your return value, update_count - you return 1 if you execute the UPDATE, but the actual number of rows affected by the statement might be something else. I suggest you use ROW_COUNT context variable instead. So your procedure would be
ALTER PROCEDURE sp_test (
IPADD Varchar(32),
HN Varchar(32),
NOTE Varchar(200) )
RETURNS ( update_count integer )
AS
BEGIN
IF(EXISTS(SELECT 1 FROM ADDRESSES a
WHERE (a.ADDRESS_TYPE = 'Reserved')
AND (a.ALIVE = 'N')
AND (a.HOST_NAME = '' OR a.HOST_NAME is NULL)
AND (a.DNS_NAME = '' OR a.DNS_NAME is NULL)
AND (a.SYSTEM_NAME = '' OR a.SYSTEM_NAME is NULL)))
THEN BEGIN
UPDATE ADDRESSES a SET
a.HOST_NAME = :HN,
a.ADDRESS_TYPE = 'Assigned',
a.NOTES = :NOTE
WHERE a.SHORT_IP_ADDRESS = :IPADD;
update_count = ROW_COUNT;
END ELSE update_count = 0;
SUSPEND;
END^

sql join problem

Query:
UPDATE EMPLOYEE AS E
INNER JOIN EMPLOYEE_TEL AS T ON E.EMP_NUMBER = T.EMP_NUMBER
SET E.FIRST_NAME = #fname
,E.MID_NAME = #mname
,E.INITIALS =#initilas
,E.SURNAME = #sname
,E.GENDER = #gender
,E.CIVIL_STATUS = #CS
,E.DOB =#datetime
,E.NIC_NUMBER = #nic
,E.ADDRESS_LINE1 =#adline1
,E.ADDRESS_LINE2 = #adline2
,E.ADDRESS_LINE3 = #adline3
,E.EMAIL = #email
,E.DESG_NO =#designo
,E.BASIC_SALARY = #sal
,E.TITLE = #title
,T.TELEPHONE=#tel
WHERE E.EMP_NUMBER=#empnum
I have tried in this SQL Server, but it came up with an error
'Msg 156, Level 15, State 1, Procedure SPUPDATEEMP, Line 21
Incorrect syntax near the keyword 'AS'.
I can't find the error. Is this wrong?
UPDATE EMPLLOYEE
SET FIRST_NAME = #fname
,MID_NAME = #mname
,INITIALS =#initilas
,SURNAME = #sname
,GENDER = #gender
,CIVIL_STATUS = #CS
,DOB =#datetime
,NIC_NUMBER = #nic
,ADDRESS_LINE1 =#adline1
,ADDRESS_LINE2 = #adline2
,ADDRESS_LINE3 = #adline3
,EMAIL = #email
,DESG_NO =#designo
,BASIC_SALARY = #sal
,TITLE = #title
WHERE EMP_NUMBER=#empnum
UPDATE EMPLOYEE_TEL
SET TELEPHONE=#tel
WHERE EMP_NUMBER=#empnum
When doing JOINS you don't need to use "as" to alias a table name.
However, when doing UPDATES you can't alias the name like you are trying to do.
UPDATE E
FROM Employee
What you're trying to do is update two tables at once - you cannot do this in SQL Server - you'll have to split this up into two separate UPDATES:
UPDATE EMPLOYEE
SET
FIRST_NAME = #fname,
MID_NAME = #mname,
.....
TITLE = #title
WHERE
EMP_NUMBER = #empnum
UPDATE EMPLOYEE_TEL
SET
TELEPHONE = #tel
WHERE
EMP_NUMBER = #empnum

Oracle - Updating one column or another based on a condition

I want to update a record in a table but based on a condition I will either update one column or another but I do not want to have 2 separate statements because the statements are very long and detailed.
Here is the basic idea with over simplification to get to the point.
PROCEDURE Animal_something(p_updater VARCHAR2)
begin
if p_updater = 'person' then
-- I want to update the modified_by
else
-- if p_updater = 'a process' I want to update modified_by_process
Update table_creatures
set animal_type = 'Dog ,
**modified_by** = 'Bob'
**or do this**
**modified_by_process =** 'creature_package'
where animal_legs = '4'
I don't want:
if p_updater = 'person' then
Update table_creatures
set animal_type = 'Dog ,
modified_by = 'Bob'
where animal_legs = '4';
else
Update table_creatures
set animal_type = 'Dog ,
modified_by_process = 'creature_package'
where animal_legs = '4';
end;
UPDATE table_creatures
SET animal_type = 'Dog',
modified_by = CASE p_updater WHEN 'person' THEN 'Bob' ELSE modified_by END,
modified_by_process = CASE p_updater WHEN 'process' THEN 'creature_package' ELSE modified_by_process END
WHERE animal_legs = 4
You could use dynamic SQL, e.g.:
PROCEDURE Animal_something(p_updater VARCHAR2)
sql_string_pt1 VARCHAR2(2000) := 'UPDATE table_creatures SET animal_type = :1';
sql_string_pt2 VARCHAR2(2000) := NULL;
sql_string_pt3 VARCHAR2(2000) := ' WHERE animal_legs = :3';
begin
if p_updater = 'person' then
sql_string_pt2 := ', modified_by = :2';
else
sql_string_pt2 := ', modified_by_process = :2';
end if;
EXECUTE IMMEDIATE sql_string_pt1 || sql_string_pt2 || sql_string_pt3
USING 'Dog', 'Bob', '4';
end;
This has two advantages over Quassnoi's answer: use of bind variables, and not needing to update both columns on every execution, which would generate redo even though the actual value is not changed.
On the downside, the statement is not validated at all at compile time.
UPDATE table_creatures
SET animal_type = 'Dog',
modified_by = DECODE(p_updater , 'person' , 'BOB' ,
'proces' , 'creature_package' ,
'GIVE DEFAULT VALUE')
WHERE animal_legs = 4;
You can try this.