Calling stored procedure sequentially from .sql file - mysql

I'm stuck here.
I've got a Procedure that I want to run X* times in a row. (*X is couple of thousands times)
The procedure based on input data does this:
1. Looks for an actions.id, if not found LEAVEs.
2. Looks for users.id, if not found, creates one and uses LAST_INSERT_ID();
3-5. Looks for summaries.id (3 types, total, daily and monthly), if not found, creates one and uses it's ID.
6. Once all required ids are collected, INSERTs new row into actions and either updates the summaries rows in a transaction, so if any fails - it does a ROLLBACK - no harm done.
7. Depending on the outcome SELECTs message.
CREATE PROCEDURE NEW_ACTION(
IN a_date TIMESTAMP,
IN u_name VARCHAR(255),
IN a_name VARCHAR(255),
IN a_chars INT,
IN url VARCHAR(255),
IN ip VARCHAR(15))
lbl_proc: BEGIN
DECLARE a_id, u_id, us_id, usd_id, usm_id, a_day, a_month, error INT;
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET error = 1;
SET error = 0;
SET a_day = DATE_FORMAT(SUBSTRING(a_date ,1,10), '%Y%m%d');
SET a_month = SUBSTRING(a_day, 1, 6);
/* 1. RETREIVING action.id */
SET a_id = (SELECT `id` FROM `actions` WHERE `name` = a_name);
IF a_id IS NULL THEN
SELECT 'error';
LEAVE lbl_proc;
END IF;
/* 2. RETREIVING users.id */
SET u_id = (SELECT `id` FROM `users` WHERE `name` = u_name);
IF u_id IS NULL THEN
INSERT INTO `users` (name) VALUES (u_name);
SET u_id = (SELECT LAST_INSERT_ID());
END IF;
/* 3. RETREIVING user_summaries.id */
SET us_id = (SELECT `id` FROM `users_summaries` WHERE `user_id` = u_id AND `action_id` = a_id);
IF us_id IS NULL THEN
INSERT INTO `users_summaries` (user_id, action_id) VALUES (u_id, a_id);
SET us_id = (SELECT LAST_INSERT_ID());
END IF;
/* 4. RETREIVING user_summaries_days.id */
SET usd_id = (SELECT `id` FROM `users_summaries_days` WHERE `day` = a_day AND `user_id` = u_id AND `action_id` = a_id);
IF usd_id IS NULL THEN
INSERT INTO `users_summaries_days` (day, user_id, action_id) VALUES (a_day, u_id, a_id);
SET usd_id = (SELECT LAST_INSERT_ID());
END IF;
/* 5. RETREIVING user_summaries_months.id */
SET usm_id = (SELECT `id` FROM `users_summaries_months` WHERE `month` = a_month AND `user_id` = u_id AND `action_id` = a_id);
IF usm_id IS NULL THEN
INSERT INTO `users_summaries_months` (month, user_id, action_id) VALUES (a_month, u_id, a_id);
SET usm_id = (SELECT LAST_INSERT_ID());
END IF;
/* 6. SAVING action AND UPDATING summaries */
SET autocommit = 0;
START TRANSACTION;
INSERT INTO `users_actions` (`date`, `user_id`, `action_id`, `chars`, `url`, `ip`) VALUES (a_date, u_id, a_id, a_chars, url, ip);
UPDATE `users_summaries` SET qty = qty + 1, chars = chars + a_chars WHERE id = us_id;
UPDATE `users_summaries_days` SET qty = qty + 1, chars = chars + a_chars WHERE id = usd_id;
UPDATE `users_summaries_months` SET qty = qty + 1, chars = chars + a_chars WHERE id = usm_id;
IF error = 1 THEN
SELECT 'error';
ROLLBACK;
LEAVE lbl_proc;
ELSE
SELECT 'success';
COMMIT;
END IF;
END;
Now, I've got raw data that I want to feed into this procedure. There's currently about 3000 rows.
I tried all the solutions I knew:
A. # mysql -uuser -ppass DB < calls.sql - Using php I've basically created a list of calls like this:
CALL NEW_ACTION('2010-11-01 13:23:00', 'username1', 'actionname1', '100', 'http://example.com/', '0.0.0.0');
CALL NEW_ACTION('2010-11-01 13:23:00', 'username2', 'actionname1', '100', 'http://example.com/', '0.0.0.0');
CALL NEW_ACTION('2010-11-01 13:23:00', 'username1', 'actionname2', '100', 'http://example.com/', '0.0.0.0');
...
This fails always (tried few times) at row 452 where it found two summary IDs (step 3).
I thought this could be due to the fact that earlier (rows 375-376) there are calls for the same user for the same action.
As if mysql didn't update tables in time, so the summary row created in CALL from line 375 isn't yet visible when line 376 gets executed - therefore creating another summary line.
Tought I'd try delaying calls...
B. Using mysql's SLEEP(duration).
This didn't change anything. Execution stops at the very same CALL again.
I'm out of ideas now.
Suggestions and help hugely appreciated.
NOTE: action names and user names repeat.
PS. Bear in mind this is one of my first procedures ever written.
PS2. Running mysql 5.1.52-community-log 64bit (Windows 7U), PHP 5.3.2 and Apache 2.2.17
EDIT
I've removed PHP related part of question to a separate question here.
EDIT2
Ok, I've deleted the first 200 calls from the .sql file. For some reason it went fine past the previous line that was stopping execution. Now it stopped at row 1618.
This would mean, that at one point a newly INSERTed summary row is no visible for a moment, therefore when it happens that one of the following iterations want to SELECT it, it's not yet accessible for them. Is that a MySQL bug?
EDIT3
Now there's another interesting thing I noticed. I investigated where two users_summaries get created. This happens (not always, but if, then it is) when there are two CALLs referring to the same user and action in close proximity. They could be next to each other or separated by 1 or 2 different calls.
If I move one of them (within .sql file) like 50-100 rows lower (executed earlier) than it's fine. I even managed to make the .sql file work as a whole. But this still doesn't really solve the problem. With 3000 rows it's not that bad, but if I had 100000, I'm lost. I can't rely on manual tweaks to .sql file.

This isn't really a solution, but a workaround.
Just to clarify, summary tables had id column as PRIMARY KEY with AUTO_INCREMENT option and indexes on both user_id and action_id column.
My investigation showed that although my procedure was looking for an entry that existed using WHERE user_id = u_id AND action_id = a_id in certain situations it didn't find it causing new row being inserted with the same user_id and action_id values - something I did not want.
Debugging the procedure showed that the summary row I was looking for, although not accessible with WHERE user_id = u_id AND action_id = a_id condition, was properly returned when calling it's id - PRIMARY KEY.
With this find I decided to change format of id column, from UNASIGNED INT with AUTO_INCEREMENT to a CHAR(32) which consisted of:
<user_id>|<action_id>
This meant that I knew exactly what the id of the row I wanted is even before it existed. This solved the problem really. It also enabled me to use INSERT ... ON DUPLICATE KEY UPDATE ... construct.
Below my updated procedure:
CREATE PROCEDURE `NEW_ACTION`(
IN a_date TIMESTAMP,
IN u_name VARCHAR(255),
IN a_name VARCHAR(255),
IN a_chars INT,
IN url VARCHAR(255),
IN ip VARCHAR(15))
SQL SECURITY INVOKER
lbl_proc: BEGIN
DECLARE a_id, u_id, a_day, a_month, error INT;
DECLARE us_id, usd_id, usm_id CHAR(48);
DECLARE sep CHAR(1);
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET error = 1;
SET sep = '|';
SET error = 0;
SET a_day = DATE_FORMAT(SUBSTRING(a_date ,1,10), '%Y%m%d');
SET a_month = SUBSTRING(a_day, 1, 6);
/* RETREIVING action.id */
SET a_id = (SELECT `id` FROM `game_actions` WHERE `name` = a_name);
IF a_id IS NULL THEN
SELECT 'error';
LEAVE lbl_proc;
END IF;
/* RETREIVING users.id */
SET u_id = (SELECT `id` FROM `game_users` WHERE `name` = u_name);
IF u_id IS NULL THEN
INSERT INTO `game_users` (name) VALUES (u_name);
SET u_id = LAST_INSERT_ID();
END IF;
/* SETTING summaries ids */
SET us_id = CONCAT(u_id, sep, a_id);
SET usd_id = CONCAT(a_day, sep, u_id, sep, a_id);
SET usm_id = CONCAT(a_month, sep, u_id, sep, a_id);
/* SAVING action AND UPDATING summaries */
SET autocommit = 0;
START TRANSACTION;
INSERT INTO `game_users_actions` (`date`, `user_id`, `action_id`, `chars`, `url`, `ip`)
VALUES (a_date, u_id, a_id, a_chars, url, ip);
INSERT INTO `game_users_summaries` (`id`, `user_id`, `action_id`, `qty`, `chars`)
VALUES (us_id, u_id, a_id, 1, a_chars)
ON DUPLICATE KEY UPDATE qty = qty + 1, chars = chars + a_chars;
INSERT INTO `game_users_summaries_days` (`id`, `day`, `user_id`, `action_id`, `qty`, `chars`)
VALUES (usd_id, a_day, u_id, a_id, 1, a_chars)
ON DUPLICATE KEY UPDATE qty = qty + 1, chars = chars + a_chars;
INSERT INTO `game_users_summaries_months` (`id`, `month`, `user_id`, `action_id`, `qty`, `chars`)
VALUES (usm_id, a_month, u_id, a_id, 1, a_chars)
ON DUPLICATE KEY UPDATE qty = qty + 1, chars = chars + a_chars;
IF error = 1 THEN
SELECT 'error';
ROLLBACK;
LEAVE lbl_proc;
ELSE
SELECT 'success';
COMMIT;
END IF;
END
Anyway, I still think there's some kind of a bug in MySQL, but I consider problem solved.

Related

MySQL / Mariadb Stored Procedure, Prepared Statement, Union, Values from dynamically created tables and column names

I'd like to create reports without having to create a pivot table in excel for every report.
I have survey software that creates a new table for each survey. The columns are named with ID numbers. So, I never know what the columns will be named. The software stores answers in two different tables depending on the 'type' of question. (text, radio button, etc.)
I manually created a table 'survey_answers_lookup' that stores a few key fields but it duplicates the answers. The procedure 'survey_report' works well and produces the required data but there is a challenge.
Since the survey tables are created when someone creates a new survey, I would need a trigger on the schema that creates a second trigger and I don't think that is possible. The second trigger would monitor the survey table and insert the data into the 'survey_answers_lookup' table after someone completes a survey.
I could edit the php software and insert the values into the survey_answers_lookup table but that would create more work when I update the software. (I'd have to update the files and then put my changes back in the files). I also could not determine where they insert the values into the tables.
Can you please help?
Edited. I posted my solution below.
Change some_user to a user who has access to the database.
CREATE DEFINER=`some_user`#`localhost` PROCEDURE `usp_produce_survey_report`(IN survey_id VARCHAR(10), IN lang VARCHAR(2))
SQL SECURITY INVOKER
BEGIN
/*---------------------------------------------------------------------------------
I do not guarantee that this will work for you or that it cannot be hacked with
with SQL injections or other malicious intents.
This stored procedure will produce output that you may use to create a report.
It accepts two arguments; The survey id (745) and the language (en).
It parses the column name in the survey table to get the qid.
It will copy the answers from the survey table to the survey_report
table if the answer is type S or K. It will get the answers from
the answers table for other types. NOTE: Other types might need to
be added to the if statement.
Additionally, the qid and id from the survey table are also copied to
the survey_report table.
Then the questions from the questions table, and answers from the answers
and survey_report tables are combined and displayed.
The data in the survey_report table is deleted after the data is displayed.
The id from the survey table is displayed as the respondent_id which may
be used to combine the questions and answers from a specific respondent.
You may have to change the prefix on the table names.
Example: survey_answers to my_prefix_answers.
Use this to call the procedure.
Syntax: call survey.usp_produce_survey_report('<SURVERY_ID>', '<LANGUAGE>');
Example: call survey.usp_produce_survey_report('457345', 'en');
use this to create the table that stores the data
CREATE TABLE `survey_report` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`qid` int(11) NOT NULL DEFAULT '0',
`survey_row_id` int(11) NOT NULL DEFAULT '0' COMMENT 'id that is in the survey_<id> table',
`answer` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
);
*/
DECLARE v_col_name VARCHAR (25);
DECLARE v_qid INT;
DECLARE v_col_count INT DEFAULT 0;
DECLARE done INT DEFAULT false;
DECLARE tname VARCHAR(24) DEFAULT CONCAT('survey_survey_',survey_id);
DECLARE counter INT DEFAULT 0;
DECLARE current_row INT DEFAULT 0;
DECLARE total_rows INT DEFAULT 0;
-- select locate ('X','123457X212X1125', 8); -- use locate to determine location of second X - returns 11
-- select substring('123457X212X1125', 11+1, 7); -- use substring to get the qid - returns 1125
DECLARE cur1 cursor for
SELECT column_name, substring(column_name, 11+1, 7) as qid -- get the qid from the column name. the 7 might need to be higher depending on the id.
FROM information_schema.columns -- this has the column names
WHERE table_name = tname -- table name created form the id that was passed to the stored procedure
AND column_name REGEXP 'X'; -- get the columns that have an X
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
SET done = FALSE;
OPEN cur1;
SET total_rows = (SELECT table_rows -- get the number of rows
FROM INFORMATION_SCHEMA.TABLES
WHERE table_name = tname);
-- SELECT total_rows;
read_loop: LOOP
FETCH cur1 INTO v_col_name, v_qid; -- v_col_name is the original column name and v_qid is the qid that is taken from the column name
IF done THEN
LEAVE read_loop;
END IF;
-- SELECT v_col_name, v_qid;
SET counter = 1; -- use to compare id's
SET current_row = 1; -- used for the while loop
WHILE current_row <= total_rows DO
SET #sql := NULL;
-- SELECT v_col_name, v_qid, counter, x;
-- SELECT counter as id, v_col_name, v_qid as qid, x;
-- SET #sql = CONCAT ('SELECT id ', ',',v_qid, ' as qid ,', v_col_name,' FROM ', tname, ' WHERE id = ', counter );
-- I would have to join the survey table below if I did not add the answer (v_col_name). I assume this is faster than another join.
SET #sql = CONCAT ('INSERT INTO survey_report(qid,survey_row_id,answer) SELECT ',v_qid, ',id,' , v_col_name, ' FROM ', tname, ' WHERE id = ', counter );
-- SELECT #sql;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- SELECT counter, x;
SET current_row = current_row + 1; -- increment counter for while loop
SET counter = counter + 1; -- increment counter for id's
END WHILE;
END LOOP; -- read_loop
CLOSE cur1;
-- SELECT * FROM survey_report
-- ORDER BY id, qid;
SET #counter = 0;
SELECT
#counter:=#counter + 1 AS newindex, -- increment the counter that is in the header
survey_report.id,
survey_report.survey_row_id as respondent_id, -- the id that copied from the survey table
survey_report.qid,
question,
IF(type IN ('S' , 'K'),
(SELECT answer
FROM survey_report
WHERE qid NOT IN (SELECT qid FROM survey_answers)
AND survey_questions.language = lang
AND survey_report.id = #counter),
(SELECT answer
FROM survey_answers
WHERE survey_questions.qid = survey_answers.qid
AND survey_report.qid = survey_questions.qid
AND survey_report.answer = survey_answers.code
AND survey_answers.language = lang
)
) AS answer
FROM survey_questions
JOIN survey_report ON survey_report.qid = survey_questions.qid
WHERE survey_questions.sid = survey_id
ORDER BY survey_report.survey_row_id, survey_report.id;
TRUNCATE TABLE survey_report;
END

MySQL procedure returning wrong value (INSERT SELECT confronting)

I'm completely new to MySQL, and have been bumping with some errors, but always I do find solutions, except for this one I can't understand how to get around it.
The following MySQL Procedure returns me a value if variable "ue" is 1 or 0 (a bunch of exists validation). The validation part (SET ue = EXISTS...) works without the rest of the code, as it should, the problem is not there. But when I do execute the command INSERT INTO SELECT, it does not work, it always return 0 as response, when it should be 1. These two lines are getting in confrontation with each other.
INSERT INTO meetup_participation SELECT user_id, event_id FROM DUAL WHERE ue=1;
SELECT ue AS response;
The procedure should add 'user id' and 'event id' into meetup_participation, and then update the row at 'users' corresponding to the user with that 'user id' to increment the 'events participated'. And it also UPDATE to increment the participation in the event with this 'event id'.
I am using the SET ue to validate things like, if user exists, if event does exists, if date of event is still valid, and if user is not already in this table. So I am passing this value as a boolean to INSERT INTO meetup_participation [...] WHERE ue = 1. After that, I do SELECT ue to inform validation returned true and procedure executed without problems.
Here is the full procedure.
CREATE DEFINER=`user`#`localhost` PROCEDURE `join_event`(IN `user_id` BIGINT(64), IN `event_id` INT) NOT DETERMINISTIC MODIFIES SQL DATA SQL SECURITY DEFINER
begin
DECLARE ue INT;
SET ue = EXISTS(SELECT 1 FROM users WHERE fb_uid=user_id) AND EXISTS(SELECT 1 FROM meetup WHERE meet_id=event_id) AND EXISTS(SELECT 1 FROM meetup WHERE date > NOW() AND meet_id = event_id) AND EXISTS(SELECT 1 FROM meetup WHERE meet_id = event_id AND participants <= max_participants) AND NOT EXISTS(SELECT 1 FROM meetup_participation WHERE fb_uid = user_id AND meet_id = event_id);
INSERT INTO meetup_participation SELECT user_id, event_id FROM DUAL WHERE ue=1;
UPDATE users SET events_participated = events_participated + 1 WHERE fb_uid=user_id AND ue=1;
UPDATE meetup SET participants = participants + 1 WHERE meet_id=event_id AND ue=1;
SELECT ue AS response;
end
Thanks in advance.
The INSERT statement is executed separately from the SET ue =... statement. I'm not sure what you are trying to accomplish, but the code makes no sense.
If you want to add records to meetup_participation based on the EXISTS tests applied to each record in the users table, you would need to apply the tests to each record in your SELECT statement as part of the INSERT.
There are also numerous syntax/grammar issues in the code as shown.
If you could provide an explanation of what you are trying to accomplish with the procedure, that might allow someone to suggest the right way to code the procedure.
Selecting ue will not tell you if the procedure completed without error. You should research mysql transactions and mysql error handling. http://www.mysqltutorial.org/mysql-error-handling-in-stored-procedures/ is a good starting point.
You might end up with something like this
drop procedure if exists p;
delimiter //
CREATE DEFINER=`root`#`localhost` PROCEDURE `p`(
IN `inue` int,
IN `user_id` BIGINT(64),
IN `event_id` INT
)
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
SQL SECURITY DEFINER
COMMENT ''
begin
DECLARE ue INT;
declare exit handler for sqlexception
begin
rollback;
insert into errors (msg) select concat('error ' ,inue,',',user_id,',',event_id);
end;
set autocommit = 0;
#set ue = inue;
SET ue = EXISTS(SELECT 1 FROM users WHERE fb_uid=user_id)
AND EXISTS(SELECT 1 FROM meetup WHERE meet_id=event_id)
#AND EXISTS(SELECT 1 FROM meetup WHERE dt > NOW() AND meet_id = event_id)
AND EXISTS(SELECT 1 FROM meetup WHERE meet_id = event_id AND ifnull(participants,0) <= max_participants)
AND NOT EXISTS(SELECT 1 FROM meetup_participation WHERE fb_uid = user_id AND meet_id = event_id)
;
select ue;
if ue = 1 then
start transaction;
INSERT INTO meetup_participation SELECT user_id, event_id,user_id, event_id;
UPDATE users SET events_participated = ifnull(events_participated,0) + 1 WHERE fb_uid=user_id = user_id;
UPDATE meetup SET participants = ifnull(participants,0) + 1 WHERE meet_id = event_id ;
commit;
end if;
SELECT ue AS response;
end //
The error table looks like this
CREATE TABLE `errors` (
`msg` varchar(2000) DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
Note I am not suggesting this is a solution appropriate to your site , you need to do the research and figure out what is best for you.

SQL Server 2008 :: Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >=

I have [ReconcileUserInformationComputed] trigger on Userinformation table
Userinformation table has below rows
[ID] ,[CompanyID] ,[Status] ,[FirstName] ,[LastName]
UserinformationComputed table has below rows
[id] ,[CompanyID] ,[law_id] ,[Status] ,[FirstName] ,[LastName]
Below is my trigger
USE [einvoice]
GO
/****** Object: Trigger [dbo].[ReconcileUserInformationComputed] Script Date: 08/27/2014 10:53:08 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[ReconcileUserInformationComputed] ON [dbo].[UserInformation] AFTER INSERT,DELETE,UPDATE
AS
IF ##ROWCOUNT = 0 -- exit trigger when zero records affected
BEGIN
RETURN
END
SET NOCOUNT ON;
IF EXISTS (SELECT * FROM INSERTED)
BEGIN
IF EXISTS (SELECT * FROM DELETED)
BEGIN
--UPDATE
UPDATE [dbo].[UserInformationComputed]
SET -- use new values from inserted
CompanyID = (SELECT CompanyID from inserted),
law_id = (SELECT ID FROM inserted),
Status = (SELECT Status FROM inserted),
FirstName = (SELECT FirstName FROM inserted),
LastName = (SELECT LastName FROM inserted),
WHERE -- use original values from deleted
law_id = (SELECT ID FROM deleted)
END
ELSE
BEGIN
--INSERT
INSERT INTO [dbo].[UserInformationComputed] (CompanyID,law_id,Status,FirstName,LastName)
SELECT CompanyID,id,Status,FirstName,LastName) FROM inserted
END
END
ELSE IF EXISTS(SELECT * FROM DELETED)
BEGIN
--DELETE
DELETE FROM [dbo].[UserInformationComputed]
WHERE law_id = (SELECT id FROM deleted)
END
when try to update multiple users on Userinformation am getting
below error
Msg 512, Level 16, State 1, Procedure ReconcileUserInformationComputed, Line 16
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I made the changes as per the answer it worked for the above trigger but same changes didnt work for another trigger
ALTER TRIGGER [dbo].[ReconcileCrossRefComputed] ON [dbo].[CrossRef] AFTER INSERT, UPDATE, DELETE
AS
IF ##ROWCOUNT = 0 -- exit trigger when zero records affected
BEGIN
RETURN
END
SET NOCOUNT ON;
IF EXISTS (SELECT * FROM INSERTED)
BEGIN
IF EXISTS (SELECT * FROM DELETED)
BEGIN
--UPDATE
UPDATE [dbo].[CrossRefComputed]
SET -- use new values from inserted
SenderId = inserted.SenderId,
ReceiverId = inserted.ReceiverId,
ForeignRef = inserted.ForeignRef,
PolicyID = inserted.PolicyID,
From inserted
WHERE -- use original values from deleted
[CrossRefComputed].SenderId = inserted.SenderId
AND [CrossRefComputed].ReceiverId = inserted.ReceiverId
END
ELSE
BEGIN
--INSERT
INSERT INTO [dbo].[CrossRefComputed] (SenderId, ReceiverId, ForeignRef, PolicyID)
SELECT SenderId, ReceiverId, Effective, PolicyID FROM inserted
END
END
ELSE IF EXISTS(SELECT * FROM DELETED)
BEGIN
--DELETE
DELETE FROM [dbo].[CrossRefComputed]
WHERE SenderId in (SELECT SenderId FROM deleted)
AND ReceiverId in (SELECT ReceiverId FROM deleted)
END
COuld anyone please help me how to fix the procedure to handle updating multiple records?
Be aware that an UPDATE or a DELETE can affect more than one record and your trigger will have to deal with them at once, in this case your "inserted" or "deleted" table will have more than one record.
You will have to use a join in your DML. Something like this:
UPDATE [dbo].[UserInformationComputed]
SET
CompanyID = inserted.CompanyID,
law_id = inserted.ID,
Status = inserted.Status,
FirstName = inserted.FirstName,
LastName = inserted.LastName
from inserted
WHERE
UserInformationComputed.law_id = inserted.ID
I haven't perfectly understood your UPDATE logic, so you'll have to adapt my code.
In your DELETE command you may have just to change "=" to "in":
DELETE FROM [dbo].[UserInformationComputed]
WHERE law_id in (SELECT id FROM deleted)
Take a look at this:
http://msdn.microsoft.com/en-us/library/ms190752.aspx

Mysql: Insert row with default new data for each user

Grateful for help with a tricky (for me) query. I am very much a mysql beginner.
The table (v3_community_fields_values) has the following columns:
id (unique id of the row, autoincrements)
user_id (the id of the user)
field_id (the id of the field type)
value (the values of that
field)
access
I have been scratching my head how to write a query that inserts a row for each user where:
a) no such row already exists, and
b) another user row exists with [field_id] of 45 (45 = user profile type) and the value of either 5 or 6
the new row should contain: [id],[user_id],'75','foobar'
Very grateful for your help.
This does it (tested):
insert into v3_community_fields_values
(user_id, field_id, value)
select user_id, 75, 'foo'
from v3_community_fields_values
where field_id = 45
and value in ('5', '6')
and user_id not in (
select user_id
from v3_community_fields_values
where field_id = 75)
See live demo on SQLFiddle.
I don't know how to implement using one sql statement, but this store procedure may help:
delimiter //
drop procedure if exists insert_something//
create procedure insert_something ()
begin
DECLARE v_user_id int default 0;
DECLARE stop int default 0;
DECLARE cursor1 CURSOR FOR select DISTINCT user_id from v3_community_fields_values where field_id = 45;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET stop=1;
OPEN cursor1;
FETCH cursor1 INTO v_user_id;
while stop <> 1 do
insert into v3_community_fields_values (user_id, field_id, `value`) values (v_user_id, '75', 'foobar');
FETCH cursor1 INTO v_user_id;
end while;
CLOSE cursor1;
end //
call insert_something()//

MySQL Stored Procedure, One INSERT not functioning with different field name?

This is quite a strange problem, so first I will post the procedure:
DELIMITER $$
USE `blahblahblah`$$
DROP PROCEDURE IF EXISTS `duplicateTradeIn`$$
CREATE DEFINER=`blahblahblah` PROCEDURE `duplicateTradeIn`(duplicate_claim INT(12))
BEGIN
DECLARE valuation INT(12) DEFAULT 0;
DECLARE claim INT(12) DEFAULT 0;
DECLARE serialNumber VARCHAR(255);
DECLARE duplicates INT(12);
DECLARE i INT(12) DEFAULT 1;
DECLARE claimID INT(12);
SET #claimID = duplicate_claim;
SET #duplicates = (SELECT COUNT(*) FROM `duplicates`);
SET #i = 1;
WHILE #i <= #duplicates DO
SET #serialNumber = (SELECT `serial` FROM `duplicates` WHERE id = #i);
INSERT INTO valuations (`pID`,`boughtproduct`,`valuationType`,`valuationAmount`,`working`,`accessories`,`age`,`brand`,`qty`,`created`,`valuationStatus`)
SELECT `pID`,`boughtproduct`,`valuationType`,`valuationAmount`,`working`,`accessories`,`age`,`brand`,`qty`,`created`,`valuationStatus`
FROM valuations WHERE vID = (SELECT vID FROM claims WHERE cID = #claimID);
SET #valuation = (SELECT LAST_INSERT_ID());
INSERT INTO claims (`vID`, `pID`, `email`, `title`, `firstname`, `lastname`, `customerType`, `company`, `position`, `address1`,`address2`,`town`,`county`,`postCode`,`telephone`,`mobile`,`emailBusiness`,`emailConsumer`,`contactPost`,`contactTelephone`,`contactMobile`,`contactEmail`,`invoiceNum`,`invoiceDate`,`invoiceInc`,`reseller`,`dateOfOrder`,`heardAbout`,`salesPerson`,`method`,`cleanseCert`,`blanccoCert`,`created`,`modified`,`noInvEmailDated`,`lateRejEmailSent`,`invAddressEmailSent`,`revalueEmailSent`,`signed`,`dated`,`sessionID`,`received`,`receiptSent`,`processedDate`,`validatedDate`,`rejectedDate`,`rejectReason`,`notes`,`claimStatus`,`origin`,`invoiceexported`)
SELECT #valuation, `pID`, `email`, `title`, `firstname`, `lastname`, `customerType`, `company`, `position`, `address1`,`address2`,`town`,`county`,`postCode`,`telephone`,`mobile`,`emailBusiness`,`emailConsumer`,`contactPost`,`contactTelephone`,`contactMobile`,`contactEmail`,`invoiceNum`,`invoiceDate`,`invoiceInc`,`reseller`,`dateOfOrder`,`heardAbout`,`salesPerson`,`method`,`cleanseCert`,`blanccoCert`,`created`,`modified`,`noInvEmailDated`,`lateRejEmailSent`,`invAddressEmailSent`,`revalueEmailSent`,`signed`,`dated`,`sessionID`,`received`,`receiptSent`,`processedDate`,`validatedDate`,`rejectedDate`,`rejectReason`,`notes`,`claimStatus`,`origin`,`invoiceexported`
FROM claims WHERE cID = #claimID;
SET #claim = (SELECT LAST_INSERT_ID());
INSERT INTO documents (`claimid`,`serial`,`filename`,`filenameOrig`,`filenameTemp`,`filetype`,`filesize`)
SELECT #claim,`serial`,`filename`,`filenameOrig`,`filenameTemp`,`filetype`,`filesize`
FROM documents WHERE claimid = #claimID;
INSERT INTO redemptions (`cID`,`pID`,`prID`,`bundleNo`,`serialNum`,`price`,`cashback`,`created`,`modified`,`claimStatus`)
SELECT #claim,`pID`,`prID`,`bundleNo`,#serialNumber,`price`,`cashback`,`created`,`modified`,`claimStatus`
FROM redemptions WHERE cID = #claimID;
INSERT INTO tradeins (`vID`,`cID`,`valuationType`,`valuationAmount`,`working`,`accessories`,`age`,`created`,`brand`,`claimStatus`)
SELECT #valuation,#claim,`valuationType`,`valuationAmount`,`working`,`accessories`,`age`,`created`,`brand`,`claimStatus`
FROM tradeins WHERE cID = #claimID;
SET #i = (#i + 1);
END WHILE;
END$$
DELIMITER ;
EDIT: Sorry!
The problem is when it tries to insert into documents (So refer to the documents table insert). If I rename the column (claimid) in the WHERE clause and INSERT to cID (by altering the table and query) it works, but otherwise it refuses to insert the new rows when it is named claimid not cID. If you have any ideas or insight into this it would be much appreciated.
To try and clarify:
Documents table with field and query as cID not claimid works.
Documents table with field and query as claimid does not insert rows.
All of the other queries seem to work fine and it only occurred to me to try cID in the documents table as that was the only difference.
Again sorry for the vagueness before and I hope the question is now clearer.
Thanks!
Just to clear this up. It is as I stated and maybe a bug in mySQL? If there is a table with a field where the ID name differs. In this example cID and claimid then it will not recognise the second declared field claimid and not perform the query.
In order for this to work I had to revise the documents table from claimID to cID.