I have problem in updating mysql table. While the problem seems somewhat strange I'm explaining it below.
I am working on user's profile update in which the data from single form is inserting/updating to two different tables but if i update the whole form information then updating data is successful but if i only update some 2 or 3 fields then updation is fail. I'm using mysql stored procedure for sql update the code is as under...
DELIMITER $$
DROP PROCEDURE IF EXISTS `usp_user_profile_save` $$
CREATE PROCEDURE `usp_user_profile_save`(IN sIntro_para VARCHAR(255), IN sBook VARCHAR(255), IN sProfileNewName VARCHAR(255),
IN iRel VARCHAR(255), IN iBdate VARCHAR(255), IN iSO INT, IN iMerital_status INT, IN iChildren INT, IN iProfession INT,
IN iIncome INT, IN iIncome_unit INT, IN iCountry INT, IN iState INT, IN iCity_or_post_code INT, IN iHeight VARCHAR(255), IN iSp INT, IN iEthnicity INT,
IN iHair_color INT, IN iHair_lenght INT, IN iEye_color INT, IN iSmoker_or_not INT, IN iUserId INT)
BEGIN
DECLARE n,n1,respCode INT;
DECLARE respMsg,dbg VARCHAR(255);
START TRANSACTION;
UPDATE `tbl_user` SET
`introduction` = sIntro_para,
`profile_picture` = sProfileNewName,
`birthdate` = iBdate,
`s_o` = iSO,
`marital_status` = iMerital_status,
`children` = iChildren,
`profession` = iProfession,
`income` = iIncome,
`income_unit` = iIncome_unit,
`my_book` = sBook,
`r_s` = iRel,
`counrty` = iCountry,
`state` = iState,
`city` = iCity_or_post_code,
`modified` = NOW(),
`modified_by` = iUserId
WHERE `id` = iUserId;
SET n = ROW_COUNT();
IF n <= 0 THEN
ROLLBACK;
ELSE
IF EXISTS (SELECT * FROM `tbl_user_physical` WHERE `tbl_user_id` = iUserId) THEN
UPDATE `tbl_user_physical` SET
`tbl_user_id` = iUserId,
`height` = iHeight,
`shape` = iSp,
`ethnicity` = iEthnicity,
`hair_color` = iHair_color,
`hair_length` = iHair_lenght,
`eye_color` = iEye_color,
`smoker_or_non_smoker` = iSmoker_or_not
WHERE `tbl_user_id` = iUserId;
SET n1 = ROW_COUNT();
ELSE
INSERT INTO `tbl_user_physical`(`tbl_user_id`, `height`, `shape`, `ethnicity`, `hair_color`, `hair_length`, `eye_color`, `smoker_or_non_smoker`) VALUES (iUserId, iHeight, iSp, iEthnicity, iHair_color, iHair_lenght, iEye_color, iSmoker_or_not);
SET n1 = LAST_INSERT_ID();
END IF;
IF n1 > 0 THEN
COMMIT;
SELECT 1 AS respCode, 'Registration successfull.' AS respMsg;
ELSE
ROLLBACK;
SELECT 0 AS respCode,'Registration couldn\'t be completed.' AS respMsg, n, n1;
END IF;
END IF;
END $$
DELIMITER;
Though i have googled my question many time with different keywords but i dont find relevant questions as mine, I have written update statement correctly but its not updating because most of the new data which is going to be update is same as old and my senior said me that update only work if there is a new set of data is submitted and used..
so, please help me to solve this problem
thanks in advance..
I lately come to know that UPDATE statement return error if we update same data. So, I've update added new column modified_date and updating this field with NOW() so that at least one column got changed and UPDATE statement returns no error.
Related
I am trying to update my db table by checking if my product_number column already exists. I know you can use the INSERT OR UPDATE ON DUPLICATE KEY but the column I am trying to use is not a primary key.
I found the following query on a stack post but I keep getting the error Unrecognized statement type. (near Duplicate) when I try run it using phpMyAdmin.
DECLARE #numrecords INT
SELECT #numrecords = count(*)
FROM users_remark
WHERE product_number = '444'
IF #numrecords > 0 THEN
UPDATE products
SET product_name = 'abc',
product_description = def,
product_detail = '',
product_price = '100',
product_price_canada = '200'
WHERE product_number = '444'
ELSE
INSERT INTO products (product_number, product_name, product_description, product_price)
VALUES (444, abc, def, 100)
END IF
Why is this query not working?
Is there a better way to achieve what I am trying to accomplish?
I created a procedure for you:
DELIMITER $$
DROP PROCEDURE IF EXISTS insert_or_update $$
CREATE PROCEDURE insert_or_update(pProduct_number INT, pProduct_name VARCHAR(200), pProduct_description VARCHAR(200), pProduct_detail VARCHAR(200), pProduct_price FLOAT(15,2), pProduct_price_canada FLOAT(15,2))
BEGIN
DECLARE numrecords INT;
SELECT count(*) INTO numrecords FROM products WHERE product_number = pProduct_number;
IF numrecords > 0 THEN
UPDATE products SET
product_name = pProduct_name,
product_description = pProduct_description,
product_detail = pProduct_detail,
product_price = pProduct_price,
product_price_canada = pProduct_price_canada
WHERE product_number = pProduct_number;
ELSE
INSERT INTO products (product_number, product_name, product_description, product_price)
VALUES (pProduct_number, pProduct_name, pProduct_description, pProduct_price);
END IF;
END $$
DELIMITER ;
To call just:
CALL insert_or_update(444, , 'abc', 'def', '', '100', '444');
I have a stored procedure as below
DROP PROCEDURE IF EXISTS maintain//
CREATE PROCEDURE maintain
(
IN inMaintainType CHAR(1), -- 'i' = Insert, 'u'= Update/Edit, 'd'= Delete
IN inEntityId INT, -- 0 for Insert Case
IN inEntityName VARCHAR(100),
IN inEntityDescription VARCHAR(100),
IN inEntityPrefix CHAR(1),
IN inStatus CHAR(1), -- 'a' = Active, 'i' = Not active
IN inEmpId INT,
OUT outReturnStatus INT,
OUT outReturnRemarks VARCHAR(100)
)
BEGIN
IF inMaintainType= 'i'
THEN
INSERT INTO Entity
(
EntityId,
EntityName,
EntityDescription,
EntityPrefix,
Status,
CreatedBy,
CreatedDate,
ModifiedBy,
ModifiedDate
)
VALUES
(
li_EntityId,
inEntityName,
inEntityDescription,
inEntityPrefix,
'a',
inEmpId,
now(),
inEmpId,
now()
);
if row_count() != 0
THEN SET outReturnStatus =0 ,
outReturnRemarks = 'Insert Successful';
ELSE SET outReturnStatus = 1,
outReturnRemarks = 'Insert Not Successful';
END IF;
END IF ;
I want to call the procedure to insert data with variables
mysql_query("CALL maintain('i','$EntityId','$EntityName','$EntityDescription','$EntityPrefix','$Status','$EmpId',#outvari1,#outvari2)")or die(mysql_error());
But it's showing me the error
Unknown column 'li_EntityId' in 'field list'
EntityId is the auto incremented field.
To clarify the comments above into an actual answer...
You have set up your table so that the field EntityId will Auto-Increment.
Because of this when you insert a record into the table you don't need to explicitly add a value for the ID field - it will do it for you.
The solution is therefore to remove the EntityId field from the INSERT INTO ... statement, and to remove the li_EntityId value from the inserted values, so only 8 arguments are passed into the remaining 8 fields.
I am doing an insert condition in oracle that when the record based on job and subjob doesnt exists, it shall insert otherwise, if it exists then it should update the rest of the value.
this is my procedure,
CREATE OR REPLACE PROCEDURE WELTESADMIN.SP_JOB_INS
(
JOB_V VARCHAR2,
SUBJOB_V VARCHAR2,
STARTDATE_V DATE,
ENDDATE_V DATE,
JOBWEIGHT_V NUMBER
)
AS BEGIN INSERT INTO PROJECT_SPAN (JOB, SUBJOB, STARTDATE, ENDDATE, WEIGHT) VALUES (JOB_V, SUBJOB_V, STARTDATE_V, ENDDATE_V, JOBWEIGHT_V);
EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
UPDATE PROJECT_SPAN SET STARTDATE = STARTDATE_V, ENDDATE = ENDDATE_V, WEIGHT = JOBWEIGHT_V WHERE JOB = JOB_V AND SUBJOB = SUBJOB_V;
END;
/
and this is from PHP Call,
$insertJobSpanSql = "BEGIN SP_JOB_INS(:JOB, :SUBJOB, :SDATE, :EDATE, :WT); END;";
$insertJobSpanParse = oci_parse($conn, $insertJobSpanSql);
oci_bind_by_name($insertJobSpanParse, ":JOB", $jobValue);
oci_bind_by_name($insertJobSpanParse, ":SUBJOB", $subJobValue);
oci_bind_by_name($insertJobSpanParse, ":SDATE", $startDateValue);
oci_bind_by_name($insertJobSpanParse, ":EDATE", $endDateValue);
oci_bind_by_name($insertJobSpanParse, ":WT", $jobWeightValue);
$insertJobSpanRes = oci_execute($insertJobSpanParse);
if ($insertJobSpanRes){
oci_commit($conn);
} else {
oci_rollback($conn);
}
problem is it keeps inserting new row with the same job and subjob value. it should be an update to the new value.
First of all, I recommend to use MERGE in such cases:
CREATE OR REPLACE PROCEDURE WELTESADMIN.SP_JOB_INS
(
JOB_V VARCHAR2,
SUBJOB_V VARCHAR2,
STARTDATE_V DATE,
ENDDATE_V DATE,
JOBWEIGHT_V NUMBER
) AS
BEGIN
merge into PROJECT_SPAN ps
using (select JOB_V, SUBJOB_V, STARTDATE_V, ENDDATE_V, JOBWEIGHT_V
from dual) new_val
on (ps.SUBJOB = new_val.SUBJOB_V and ps.JOB = new_val.JOB_V)
when matched then update
set STARTDATE = new_val.STARTDATE_V,
ENDDATE = new_val.ENDDATE_V,
WEIGHT = new_val.JOBWEIGHT_V
when not matched then insert (JOB, SUBJOB, STARTDATE, ENDDATE, WEIGHT)
values (new_val.JOB_V, new_val.SUBJOB_V, new_val.STARTDATE_V,
new_val.ENDDATE_V, new_val.JOBWEIGHT_V );
END;
/
If it still not updating values, use package DBMS_OUTPUT or logging into a table to make sure, that new and old JOB and SUBJOB really the same.
Oracle raises DUP_VAL_ON_INDEX when a DDL statement violates a primary key or unique key constraint. So for your code to work you need to define a primary key on (job, subjob) or else build a unique index on that pair.
Oracle provides an easier way of implementing upserts, in the form of the MERGE statement:
CREATE OR REPLACE PROCEDURE WELTESADMIN.SP_JOB_INS
(
JOB_V VARCHAR2,
SUBJOB_V VARCHAR2,
STARTDATE_V DATE,
ENDDATE_V DATE,
JOBWEIGHT_V NUMBER
)
AS BEGIN
merge into project_span ps
using ( select job_v, subjob_v, startdate_v, enddate_v, jobweight_v from dual ) q
on (ps.job = q.job_v
and ps.subjob = q.subjob_v)
when not matched then
insert (job, subjob, startdate, enddate, weight)
values (q.job_v, q.subjob_v, q.startdate_v, q.enddate_v, q.jobweight_v);
when matched then
update
set startdate = q.startdate_v
, enddate = q.enddate_v
, weight = q.jobweight_v
;
END;
The MERGE statement is in the documentation. Find out more.
I call the procedure with php and the relevant variables. I need the latest IDs to use it for the next insert, so I set variables with SCOPE_IDENTITY. The return ist always the value of appointment_id ?!
ALTER proc [dbo].[insertPersonWithCmoFmo]
#appointment_id int,
#kostenstelle varchar(50),
#vorname varchar(50),
#nachname varchar(50),
#ci_nummer int,
#anzahl_monitore_old int,
#raum varchar(50),
#gebäude varchar(50),
#bemerkung text,
#hardware_typ varchar(50),
#anzahl_monitore_new varchar(50),
#zubehör text
as
DECLARE
#latestPersonID int,
#latestCmoID int,
#latestFmoID int
BEGIN
INSERT INTO [RC.Persons] (kostenstelle, vorname, nachname) VALUES (#kostenstelle, #vorname, #nachname);
SET #latestPersonID = (SELECT SCOPE_IDENTITY())
INSERT INTO [RC.CMO] (ci_nummer, anzahl_monitore, raum, gebäude, bemerkung) values (#ci_nummer, #anzahl_monitore_old, #raum, #gebäude, #bemerkung);
SET #latestCmoID = (SELECT SCOPE_IDENTITY())
INSERT INTO [RC.FMO] (hardware_typ, anzahl_monitore, zubehör) values (#hardware_typ, #anzahl_monitore_new, #zubehör);
SET #latestFmoID = (SELECT SCOPE_IDENTITY())
INSERT INTO [RC.Appointments_RC.CMO] (cmo_id, appointment_id) values (#latestCmoID, #appointment_id);
INSERT INTO [RC.Persons_RC.CMO] (cmo_id, person_id) VALUES (#latestCmoID, #latestPersonID);
INSERT INTO [RC.Persons_RC.FMO] (fmo_id, person_id) VALUES (#latestFmoID, #latestPersonID);
return #latestFmoID
END
This is the exec code. Why the is a "N" before all varchar type?
USE [Testtable]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[insertPersonWithCmoFmo]
#appointment_id = 52,
#kostenstelle = N'54',
#vorname = N'testname',
#nachname = N'testlastname',
#ci_nummer = 111222333,
#anzahl_monitore_old = 2,
#raum = N'255',
#gebäude = N'KWA12',
#bemerkung = N'blablabla',
#hardware_typ = N'Desktop',
#anzahl_monitore_new = N'4',
#zubehör = N'Test'
SELECT 'Return Value' = #return_value
GO
SQL Output:
Meldung 2601, Ebene 14, Status 1, Prozedur insertPersonWithCmoFmo, Zeile 36
Cannot insert duplicate key row in object 'dbo.RC.FMO' with unique index 'NonClusteredIndex-20140116-143317'. The duplicate key value is ().
The statement has been terminated.
Is there something about the error message you don't understand? One or more of the tables has a unique constraint (or index) and you are trying to insert the same values in the table. For example, the persons table might already have the person in it.
The N before the string explicitly makes the string use wide characters.
Your stored procedure probably needs to be rewritten. You need to check errors that might occur along the way. Traditionally, a value would be returned using an OUTPUT parameter.
The safest way to get the new id value is to use the output clause of the insert statement (see the documentation here).
The N indicates nvarchar instead of varchar.
See:
https://stackoverflow.com/questions/10025032/what-is-the-meaning-of-the-prefix-n-in-t-sql-statements
I have the following stored procedure:
proc_main:begin
declare done tinyint unsigned default 0;
declare dpth smallint unsigned default 0;
create temporary table hier(
AGTREFERRER int unsigned,
AGTNO int unsigned,
depth smallint unsigned default 0
)engine = memory;
insert into hier values (p_agent_id, p_agent_id, dpth);
/* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */
create temporary table tmp engine=memory select * from hier;
while done <> 1 do
if exists( select 1 from agents a inner join hier on a.AGTREFERRER = hier.AGTNO and hier.depth = dpth) then
insert into hier
select a.AGTREFERRER, a.AGTNO, dpth + 1 from agents a
inner join tmp on a.AGTREFERRER = tmp.AGTNO and tmp.depth = dpth;
set dpth = dpth + 1;
truncate table tmp;
insert into tmp select * from hier where depth = dpth;
else
set done = 1;
end if;
end while;
select
a.AGTNO,
a.AGTLNAME as agent_name,
if(a.AGTNO = b.AGTNO, null, b.AGTNO) as AGTREFERRER,
if(a.AGTNO = b.AGTNO, null, b.AGTLNAME) as parent_agent_name,
hier.depth,
a.AGTCOMMLVL
from
hier
inner join agents a on hier.AGTNO = a.AGTNO
inner join agents b on hier.AGTREFERRER = b.AGTNO
order by
-- dont want to sort by depth but by commission instead - i think ??
-- hier.depth, hier.agent_id;
a.AGTCOMMLVL desc;
drop temporary table if exists hier;
drop temporary table if exists tmp;
end proc_main
While the function does its job well - it only currently allows sorting via AGTCOMMLVL descending order. The stored procedure's purpose is to match a memberID with their parentID and associated COMMLVL. Once paired appropriately,I use the memberID in a second query to return information about that particular member.
I would like to be able to sort by any number of filters but have the following problems:
I can't seem to find a way to pass a variable into the stored procedure altering its sorting by field.
Even if I could - the sort may actually only contain data from the second query (such as first name, last name, etc)
Running a sort in the second query does nothing even though syntax is correct - it always falls back to the stored procedure's sort.
any ideas?
EDIT
My php uses mysqli with code:
$sql = sprintf("call agent_hier2(%d)", $agtid);
$resulta = $mysqli->query($sql, MYSQLI_STORE_RESULT) or exit(mysqli_error($mysqli));
If you want to sort by input parameter of the stored procedure, you need to use Prepared staments
For example,
DELIMITER //
CREATE PROCEDURE `test1`(IN field_name VARCHAR(40) )
BEGIN
SET #qr = CONCAT ("SELECT * FROM table_name ORDER BY ", field_name);
PREPARE stmt FROM #qr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)");
$value = 'hello';
$stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);
// call the stored procedure
$stmt->execute();
print "procedure returned $value\n";
This also works in Mysql 5.6
DELIMITER //
CREATE PROCEDURE `test1`(IN field_name VARCHAR(40) )
BEGIN
"SELECT * FROM table_name ORDER BY ", field_name);
END //