I'm trying to create some database triggers post database created, by adding them to a sql file that is called from sqldb.map.
However, to create triggers, I need to use the delimiter command to change the delimiter to something besides the semi-colon. This fails, and the result trigger creation fails, both with the standard, you have a syntax error message.. I can run a simple sql statement this way, but it doesn't like delimiter.
Any thoughts?
delimiter //
CREATE TRIGGER `SHOW_ADD_NEWS_ITEM`
AFTER INSERT ON `show`
FOR EACH ROW
BEGIN
declare username varchar(255);
IF NEW.privacy_key IS NOT NULL AND NEW.privacy_key <> 'PRIVATE' and (NOT EXISTS (select id from feed_friend_activity
where location_identifier = NEW.uuid and user_id = NEW.user_id and event_type = 'published show')) THEN
select concat(user.first_name,user.last_name) into username from user where user.id = NEW.user_id;
insert into feed_friend_activity
(location_identifier,user_id,event_type,user_name,item_name,created_on)
values (NEW.uuid,NEW.user_id,'published show',username,NEW.name,NEW.created_on);
END IF;
END
//
Propel 1.6.7 now supports DELIMITER. See this Pull Request for more information. If your SQL is valid, then it will work fine with 1.6.7 or upper.
Related
I have tried everything but nothing can solve this.PLS-00049: bad bind variable 'NEW.BLOODBANKID' keep appearing. Please help me.
CREATE OR REPLACE TRIGGER count_stock
AFTER INSERT OR UPDATE ON blood
FOR EACH ROW
DECLARE
v_countblood NUMBER;
BEGIN
SELECT COUNT(bloodid) INTO v_countblood
FROM blood
WHERE bloodbankid = :NEW.bloodbankid
AND bloodtype = :NEW.bloodtype;
IF v_countblood < 0 THEN
RAISE_APPLICATION_ERROR(-20201,'There is no blood');
END IF;
END;
The error indicates that there is no column "BLOODBANKID" in the table "BLOOD".
Either it doesn't exist at all in the table or you used double quotes on the column in your CREATE TABLE statement, thus making the column case sensitive.
If for instance your CREATE TABLE statement looks like this:
create table blood("bloodbankid" number(18), ...);
Then there is a column "bloodbankid" in the table, but no column "BLOODBANKID".
When we access a row without quotes as in
select BLOODBANKID from blood where BloodBankId = 123;
then Oracle converts this internally into "BLOODBANKID". As the same applies to CREATE TABLE, the column names usually match. If you used quotes in the CREATE TABLE statement, however, then you must use the same upper/lower case with quotes in every statement:
select "bloodbankid" from blood where "bloodbankid" = 123;
So, if this is the case, I'd recommend you re-create the table with case insensitive columns.
(Apart from this your trigger doesn't make sense anyway, as has already been mentioned in the request comments.)
I want update all values in my tables, but this can kill my database
UPDATE Table_1
SET Value = 'Some string with but changed'
where value = 'Some string without changes';
Can I do this by procedures, and it guarantee that it will not perform in infinty please i need some tips?
Edit
I read about cursors, but how can i use it
Your SQL seems fine and that is the preferred solution. A cursor will normally be far, far slower.
If you cannot create an index and the update above is really that slow, try the following. Considering I don't have the rest of the table definition to work with, I assume your primary key is a single field named ID:
First, create a temporary table with only the matching records:
CREATE TEMPORARY TABLE temp as
SELECT *
FROM Table_1
WHERE value = 'Some string without changes';
Then, update using this temporary table:
UPDATE Table_1 SET
Table_1.Value = 'Some string with but changed'
WHERE EXISTS (
SELECT *
FROM Temp
WHERE Temp.ID = Table_1.ID
);
Another approach if your DB is higher than 11g R1 version. Oracle has provided a beautiful package called DBMS_PARALLEL_EXECUTE which is used for large DMLS or any process which can be split into chunks and can be parallely done.
I am writing the below trigger where i am getting the error while to trying to insert the value for this field FIELD_OLD_VALUE,FIELD_NEW_VALUE. I have to insert the value for this fields based on Select query but i am getting the error as SQL Statement Ignored ORA-000936 missing expression in Oracle trigger. I dont want to use variable for field FIELD_OLD_VALUE,FIELD_NEW_VALUE because i have written the insert statement only for ENV_ID field in this question and i have many other fields to add in this trigger. So its difficult to decalre variable and maintain for each and every field.
create or replace TRIGGER RATOR_MONITORING_CONFIGURATION."TRG_TRK_KPI_DEFINITION" AFTER UPDATE ON RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION
FOR EACH ROW
BEGIN
--NEU
IF NOT :old.ENV_ID=:new.ENV_ID THEN
INSERT INTO RATOR_MONITORING_CONFIGURATION.FIELD_TRACKING (FIELD_TRACKING_ID,TABLE_NAME,TABLE_ID, FIELD_NAME,FIELD_OLD_VALUE,FIELD_NEW_VALUE,USER_ID, TIMESTAMP)
VALUES (FIELD_TRACKING_SEQ.NEXTVAL,'KPI_DEFINITION',:new.KPI_DEF_ID,'Environment',to_char(Select NAME FROM ENVIRONMENT WHERE ENV_ID =:old.ENV_ID),to_char(Select NAME FROM ENVIRONMENT WHERE ENV_ID =:new.ENV_ID),:new.LAST_UPDATED_BY,:new.LAST_UPDATED_DATE );
END IF;
END;
If you use subqueries as parameters you need to wrap them in extra parentheses:
to_char((Select NAME FROM ENVIRONMENT WHERE ENV_ID =:old.ENV_ID))
In Postgres, I can write
INSERT .. RETURNING *
To retrieve all values that had been generated during the insert. In Oracle, HSQLDB, I can use
String[] columnNames = ...
PreparedStatement stmt = connection.prepareStatement(sql, columnNames);
// ...
stmt.execute();
stmt.getGeneratedKeys();
To retrieve all values that had been generated. MySQL is a bit limited and only returns columns that are set to AUTO_INCREMENT. But how can this be done with Sybase SQL Anywhere? The JDBC driver does not implement these methods, and there is no INSERT .. RETURNING clause, as in Postgres. Is there way to do it, other than maybe running
SELECT ##identity
immediately after the insert?
My current implementation executes three consecutive SQL statements:
-- insert the data first
INSERT INTO .. VALUES (..)
-- get the generated identity value immediately afterwards
SELECT ##identity
-- get the remaining values from the record (possibly generated by a trigger)
SELECT * FROM .. WHERE ID = :previous_identity
The third statement can be omitted, if only the ID column is requested
I am familiar with Sybase which allows queries with format: IF EXISTS () THEN ... ELSE ... END IF (or very close). This a powerful statement that allows: "if exists, then update, else insert".
I am writing queries for DB2 on IBM iSeries box. I have seen the CASE keyword, but I cannot make it work. I always receive the error: "Keyword CASE not expected."
Sample:
IF EXISTS ( SELECT * FROM MYTABLE WHERE KEY = xxx )
THEN UPDATE MYTABLE SET VALUE = zzz WHERE KEY = xxx
ELSE INSERT INTO MYTABLE (KEY, VALUE) VALUES (xxx, zzz)
END IF
Is there a way to do this against DB2 on IBM iSeries? Currently, I run two queries. First a select, then my Java code decides to update/insert. I would rather write a single query as my server is located far away (across the Pacific).
+UPDATE+
DB2 for i, as of version 7.1, now has a MERGE statement which does what you are looking for.
>>-MERGE INTO--+-table-name-+--+--------------------+----------->
'-view-name--' '-correlation-clause-'
>--USING--table-reference--ON--search-condition----------------->
.------------------------------------------------------------------------.
V |
>----WHEN--+-----+--MATCHED--+----------------+--THEN--+-update-operation-+-+----->
'-NOT-' '-AND--condition-' +-delete-operation-+
+-insert-operation-+
'-signal-statement-'
See IBM i 7.1 InfoCenter DB2 MERGE statement reference page
DB/2 on the AS/400 does not have a conditional INSERT / UPDATE statement.
You could drop the SELECT statement by executing an INSERT directly and if it fails execute the UPDATE statement. Flip the order of the statements if your data is more likely to UPDATE than INSERT.
A faster option would be to create a temporary table in QTEMP, INSERT all of the records into the temporary table and then execute a bulk UPDATE ... WHERE EXISTS and INSERT ... WHERE NOT EXISTS at the end to merge all of the records into the final table. The advantage of this method is that you can wrap all of the statements in a batch to minimize round trip communication.
You can perform control-flow logic (IF...THEN...ELSE) in an SQL stored procedure. Here's sample SQL source code:
-- Warning! Untested code ahead.
CREATE PROCEDURE libname.UPSERT_MYTABLE (
IN THEKEY DECIMAL(9,0),
IN NEWVALUE CHAR(10) )
LANGUAGE SQL
MODIFIES SQL DATA
BEGIN
DECLARE FOUND CHAR(1);
-- Set FOUND to 'Y' if the key is found, 'N' if not.
-- (Perhaps there's a more direct way to do it.)
SET FOUND = 'N';
SELECT 'Y' INTO FOUND
FROM SYSIBM.SYSDUMMY1
WHERE EXISTS
(SELECT * FROM MYTABLE WHERE KEY = THEKEY);
IF FOUND = 'Y' THEN
UPDATE MYTABLE
SET VALUE = NEWVALUE
WHERE KEY = THEKEY;
ELSE
INSERT INTO MYTABLE
(KEY, VALUE)
VALUES
(THEKEY, NEWVALUE);
END IF;
END;
Once you create the stored procedure, you call it like you would any other stored procedure on this platform:
CALL UPSERT_MYTABLE( xxx, zzz );
This slightly over complex piece of SQL procedure will solve your problem:
IBM Technote
If you want to do a mass update from another table then have a look at the MERGE statement which is an incredibly powerful statement which lets you insert, update or delete depending on the values from another table.
IBM DB2 Syntax