How to update all rows for a column - sql-server-2008

I am trying to update multiple rows on one column (SQL Server 2008). The column I need to update has insert and update trigger. When I run this script I got an error message:
UPDATE htable
SET Isverified=1
WHERE columnname IN ('122','566','652')
Error:
Msg 512, Level 16, State 1, Procedure mydatabasename, Line 22
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I don't know how true this is but I want to believe due to the trigger define on this column. Did any want know how I can achieve this
here is the trigger:
ALTER TRIGGER [dbo].[sendTodbase]
ON [dbo].[htable]
AFTER UPDATE
AS
BEGIN DISTRIBUTED TRANSACTION
SET NOCOUNT ON
--CHECK IF DATAENTRY COLUMN IS UPDATED
IF UPDATE(Isverified) begin
declare #dEVer bit declare #rcNum varchar(50)
declare #idenNum varchar(50) declare #docId bigint
--GET INSERTED VALUE AND CHECK IF IT's (YES) THEN CONTINUE...
select #dEVer = (select Isverified from inserted i)
if #dEVer = 1 begin
--END CHECK, IF DE IS COMPLETED CONTINUE----
COMMIT TRAN

Exception is probably generated by:
select #dEVer = (select Isverified from inserted i)
TSQL interpreter expects no more than one row returned by select Isverified from inserted i subquery.
Your update query affets more than one row and exception Subquery returned more than 1 value is generated.

Try Something like this:
Update mydatble set ColumnName = <Require value>
where columnname in ('122','566','652')

Related

Can I use subquery in a user-defined function

I try to use subquery in mysql custom user-defined function I get an error so could u help me with one example.
Here is my code:
CREATE DEFINER=`root`#`localhost` FUNCTION `findsubName`(counts INT)
RETURNS varchar(255) CHARSET utf8
BEGIN
DECLARE result VARCHAR(500) DEFAULT NULL;
DECLARE v_name VARCHAR(200);
DECLARE finished INT(1) DEFAULT 0;
DECLARE my_cursor CURSOR FOR
SELECT id, (SELECT t_name FROM ajctb_titles b WHERE a.jt_id=b.t_id)
as tableName FROM ajctb_vacancies a limit counts;
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET finished = 1;
OPEN my_cursor;
calc_change: LOOP
FETCH my_cursor INTO v_name;
IF finished THEN
LEAVE calc_change;
END IF;
IF result<>'' THEN
SET result = CONCAT_WS(',',result,v_name);
ELSE
SET result = v_name;
END IF;
END LOOP calc_change;
CLOSE my_cursor;
RETURN result;
END
Error message:
Error Code: 1328. Incorrect number of FETCH variables
Error message: Error Code: 1328. Incorrect number of FETCH variables
Error messages attempt to tell you what the problem is. It is in the FETCH. Looking at the documentation:
13.6.6.3 Cursor FETCH Syntax
FETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...
This statement fetches the next row for the
SELECT statement associated with the specified cursor (which must be
open), and advances the cursor pointer. If a row exists, the fetched
columns are stored in the named variables. The number of columns
retrieved by the SELECT statement must match the number of output
variables specified in the FETCH statement.
https://dev.mysql.com/doc/refman/8.0/en/fetch.html
2 columns in your query:
SELECT
id
, (
SELECT
t_name
FROM ajctb_titles b
WHERE a.jt_id = b.t_id
)
AS tableName
means 2 variables are needed the FETCH
It hasn't even attempted the subquery yet.
Regarding that correlated subquery it could be a problem. When you use a subquery in the select clause like this it MUST return no more then one value. So you should use limit 1 if you continue with that subquery.
That subquery can be replaced with a join. e.g.
SELECT
id
, b.t_name AS tableName
FROM ajctb_vacancies a
LEFT JOIN ajctb_titles b ON a.jt_id = b.t_id
You may want to use an INNER JOIN if you must always have a non-null tablename returned.

MySQL : Stored procedure returns null for last_insert_id

I'm facing a problem with SP in mySql when I want to select my identete it gives always null as value.
DELIMITER $$
CREATE PROCEDURE insert_details_facture(IN typefacture INT,
IN codeactivite VARCHAR(255),
IN qte INT,
IN pu DOUBLE,
IN unite VARCHAR(255),
IN montant DOUBLE)
BEGIN
DECLARE identete INT;
SELECT identete = numfacture FROM entetefacture WHERE numfacture = LAST_INSERT_ID();
END$$
When I execute this it gives identite = numfacture as column's name and null as value.
CALL insert_details_facture(10,'l',10,12,'l',20)
Check Here.
With no argument, LAST_INSERT_ID() returns a BIGINT UNSIGNED (64-bit) value representing the first automatically generated value successfully inserted for an AUTO_INCREMENT column as a result of the most recently executed INSERT statement.
so result you are getting is obvious.
to get last record you can use limit.
SET identete = (SELECT numfacture FROM entetefacture ORDER BY id DESC LIMIT 1);
LAST_INSERT_ID() is not guaranteed to have a valid value. For instance, the documentation states:
If the previous statement returned an error, the value of
LAST_INSERT_ID() is undefined. For transactional tables, if the
statement is rolled back due to an error, the value of
LAST_INSERT_ID() is left undefined.
Similarly, if there have been no database changes for the current session, then the value will be undefined.
Also, if you want to set the value, then use := in a select:
SELECT identete := numfacture
FROM entetefacture
WHERE numfacture = LAST_INSERT_ID();
Why not just get the last row in the table using limit?
SET identete = (SELECT numfacture FROM entetefacture ORDER BY id LIMIT 1);

Updating a column name of a same table which has a parent child relationship using mysql

I searched a lot of doing a task but found no appropriate solution.
Basically the scenario is. I have a user_comment table in which there are 5 column(id,parent_id,user_comments,is_deleted,modified_datetime). There is a parent child relationship like 1->2,1->3,2->4,2->5,5->7 etc. Now i am sending the id from the front end and i want to update the column is_deleted to 1 and modified_datetime on all the records on
this id as well as the all the children and children's of children.
I am trying to doing this by using a recursive procedure. Below is the code of my procedure
CREATE DEFINER=`root`#`localhost` PROCEDURE `user_comments`(
IN mode varchar(45),
IN comment_id int,
)
BEGIN
DECLARE p_id INT DEFAULT NULL ;
if(mode = 'delete')
then
update user_comment set is_deleted = 1, modified_datetime = now()
where id = comment_id ;
select id from user_comment where parent_id = comment_id into p_id ;
if p_id is not null
then
SET ##GLOBAL.max_sp_recursion_depth = 255;
SET ##session.max_sp_recursion_depth = 255;
call user_comments('delete', p_id);
end if;
end if;
END
By using this procedure it give me an error of more than one row.
If i return the select query without giving it to variable then shows me the the appropriate results on the select query but i have to call this procedure recursively based on getting the ids of the select query.
I need help i have already passed 2 days into this.
I used cursor also. Below is the code of cursor
CREATE DEFINER=`root`#`localhost` PROCEDURE `user_comments`(
IN mode varchar(45),
IN comment_id int,
)
BEGIN
DECLARE p_emp int;
DECLARE noMoreRow INT;
DECLARE cur_emp CURSOR FOR select id from user_comment where parent_id = comment_id ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET noMoreRow = 0;
if(mode = 'delete')
then
OPEN cur_emp;
LOOPROWS: LOOP
IF noMoreRow = 0 THEN
update user_comment set is_deleted = 1, modified_datetime = now() where id = comment_id
CLOSE cur_emp;
LEAVE LOOPROWS;
END IF;
FETCH cur_emp INTO p_emp;
update user_comment set is_deleted = 1, modified_datetime = now() where id = p_emp ;
SET ##GLOBAL.max_sp_recursion_depth = 255;
SET ##session.max_sp_recursion_depth = 255;
call user_comments('delete', p_emp);
END LOOP;
end if;
END
After using cursor i am getting a thread error.i don't know how can overcome this problem!!!
Mysql's documentation on select ... into varlist clearly says:
The selected values are assigned to the variables. The number of
variables must match the number of columns. The query should return a
single row. If the query returns no rows, a warning with error code
1329 occurs (No data), and the variable values remain unchanged. If
the query returns multiple rows, error 1172 occurs (Result consisted
of more than one row). If it is possible that the statement may
retrieve multiple rows, you can use LIMIT 1 to limit the result set to
a single row.
Since you wrote in the OP that a comment can be parent of many comments, using simple variables cannot be a solution. You should use a CURSOR instead, that can store an entire resultset.
You loop through the records within the cursos as shown in the sample code in the above link and call user_comments() in a recursive way.
UPDATE
If your receive
Error Code: 1436. Thread stack overrun
error, then you can do 2 things:
Increase the thread_stack setting in the config file and restart mysql server.
You can try to simplify your code to use less recursions and therefore less stack space. For example, when you fetch all children into the cursor, then rather calling the user_comments() recursively for each, you can set all direct children's status within the code and call the function recirsively on grand-childrens only (if any). You can also change your data structure and use nested set model to approach hierarchical structures.
Nested set model is more complex to understand, it is less resource intensive to traverse, but more resource intensive to maintain.

MySQL procedure gone wrong

I have a MySQL database in which I have the following rows (by exemple) created by default (id, task and case may be different but the current value is always 1)
....idtaskcaseuser............datecurrent
238......31001.....0..............null..........1
239......41001.....0..............null..........1
I have to randomly create rows like this with insert statement (new rows). As you can see a date is filled and de current equal 0
....idtaskcaseuser............datecurrent
240......51001.....12015.04.03..........0
241......21002.....12015.04.03..........0
When I come across one of the lines created by default I want to use an update instead of an insert statement.
So I created the following procedure in MySQL
DELIMITER //
DROP PROCEDURE IF EXISTS FillProgress//
CREATE PROCEDURE FillProgress ( get_case INT(10),get_task INT(10), get_user INT(10) )
BEGIN
DECLARE test tinyint(1);
SET test = (SELECT COUNT(*) FROM progress WHERE case_id = get_case AND task_id = get_task);
IF test = 1 THEN
UPDATE progress SET current = 0, date = NOW(), user_id = get_user WHERE task_id = get_id AND case_id = get_case;
ELSE
INSERT INTO progress(task_id,case_id,user_id,date,current) VALUES (get_task,get_case,get_user,NOW(),0);
END IF;
END; //
DELIMITER ;
I use count to see if a already have a row with the same case and task. If it's true (test=1) I use UPDATE, otherwise and use INSERT.
If I test with the following row already wrote in the database
....idtaskcaseuserdatecurrent
241......41001.....0..null..........1
I use CALL FillProgress(1001,4,1);
The row is not updated, but I do not have any error message.
11:38:02 CALL FillProgress(1001,4,1) 0 row(s) affected 0.000 sec
And if I manually use my update query
UPDATE progress SET current = 0, date = NOW(), user_id = 1 WHERE task_id = 4 AND case_id = 1001;
It works like a charm.
The insert query also works fine.
The UPDATE query within the procedure has a "WHERE task_id = get_id" clause, however I don't see get_id being defined in the procedure; there is a "get_task" parameter for the stored procedure, though.

'subquery returns more than 1 value' ERROR in Stored procedure creation

learning the concept of procedures and thought of trying something on my own.
1)
i have a table having the foll columns
loan_no
r_interest
loan_amt
loan_date
time_yr
2)
i created a procedure
create procedure proc_update1
as
begin
declare #interest as decimal
declare #rate as int
declare #p as int
declare #n as int
set #rate=(select r_interest from bank_details)
set #p=(select loan_amt from bank_details)
set #n=(select time_yr from bank_details)
set #interest =(#p*#n*#rate)/100
alter table loan_details add interest1 decimal
update loan_details set interest1=#interest
end
3) when i executed using exec proc_update1
Msg 512, Level 16, State 1, Procedure proc_update1, Line 9
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression. Msg 512, Level 16, State 1, Procedure proc_update1,
Line 10
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression. Msg 512, Level 16, State 1, Procedure proc_update1,
Line 11
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression. Msg 2705, Level 16, State 4, Procedure proc_update1,
Line 13
have i misunderstood anything ???
Edit: I misunderstood the question. You have a table with loan amounts, time, and interest rates. You have a column in some table, either the original or a new table. You can update the rows with the following query.
UPDATE loan_details
SET interest1 =
(
SELECT (loan_amt*time_yr*r_interest)/100 AS 'interest'
FROM bank_details
)
However you should have a primary key so you could add:
WHERE loan_details.Account = bank_details.AccountId
If you want to add a column in a reusable stored procedure you must first check if the column is already there before proceeding. You do this by querying sys.columns. If the column doesn't exist then it is added. If the column doesn't exist then nothing happens. Regardless, you move forward to with your UPDATE loan_details.
IF EXISTS
(
SELECT * FROM sys.columns
WHERE Name = N'columnName' AND OBJECT_ID = OBJECT_ID(N'tableName')
)
BEGIN
ALTER TABLE MyTable
ADD NewColumn1 INT DEFAULT 1
END