I saw another post explaining the use of sequence table to create prefixed AUTO INCREMENT ID.
Link to referenced post
SQL Fiddle
http://sqlfiddle.com/#!2/0ed88/1
I need the generated auto increment format to be: YYMM + AUTO INCREMENT VALUE that reset every month. For example now is January, 2015. The generated id should be: 15011, 15012, 15013, etc. Next month February 2015, the generated id should be: 15021, 15022, 15023, etc. I can use the above method to generate the prefix, however how do I reset the AUTO INCREMENT value each month? Database is InnoDB. Any help will be greatly appreciated :)
MODIFIED CODE
CREATE TABLE table1_seq
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
)|
CREATE TABLE Table1
(
id VARCHAR(7) NOT NULL PRIMARY KEY DEFAULT '0', name VARCHAR(30)
)|
CREATE TRIGGER tg_table1_insert
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
INSERT INTO table1_seq VALUES (NULL);
SET NEW.id = CONCAT(DATE_FORMAT(NOW(),'%y%m'), LAST_INSERT_ID());
END |
INSERT INTO Table1 (name) VALUES ('Jhon'), ('Mark')|
If you have a field DATE or DATETIME in your table then this solution maybe can help you.
Let say your table name my_table and has PK id (INT) and also a field bila (DATE). I just need to get last (biggest) id in current month from my_table then add by 1.
SET #mos= (SELECT MAX(id) FROM my_table WHERE MONTH(`bila`) = MONTH(NOW()) AND YEAR(`bila`) = YEAR(NOW()));
SET #mos = IF(
#mos IS NULL,
CONCAT(YEAR(NOW()),MONTH(NOW()),'001'),
#mos + 1
);
Then u can use #mos in your query next
To reset the AUTO_INCREMENT value, drop and recreate the table1_seq table. Given your example, a TRUNCATE statement would be sufficient (given that there aren't any foreign keys, and we assume the table is using either the MyISAM or InnoDB engine).
TRUNCATE TABLE table1_seq ;
(MySQL behavior for this statement is to create a new, empty table, with the AUTO_INCREMENT set back to the value when the table was created.)
This effectively achieves the same result as a DROP table followed by CREATE table.
That answers the question you asked. As a side note, generating a key value this way usually turns out to be a bad idea.
i've relied on the last answer above, i've used the orderDate field from my table and compared it with the current date during insertion , to decide finally if i want to reset or increment the purchaseOrderRef field:
The aim is to insert custom auto increment order id (field name: "purchaseOrderRef" ) with the format DD-MM-XXX in table [Products_SumOrders]. such that it resets the XXX to 0 automatically every month:
USE [Mydatabase] -- here you need to use your own database
GO
/****** Object: Trigger [dbo].[customAutoIncrement] Script Date: 10/1/2016 10:07:41 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[customAutoIncrement]
ON [dbo].[Products_SumOrders]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
declare #maxOrderID int;
declare #maxOrderRef nvarchar(max);
declare #relativeID varchar(max);
declare #orderId int;
select #orderId =orderid from inserted;
print(#orderId);--allow me to display the inserted order id
SET #maxOrderID = (SELECT Max(orderid) FROM [Products_SumOrders] WHERE MONTH([OrderDate]) = (MONTH(GETDATE())) AND YEAR([OrderDate]) = YEAR(GETDATE()) and orderid < #orderId );
print(#maxOrderID);--last added order
--custom month format (always MM):
declare #mon int;
declare #stringMon nvarchar(10);
set #mon= MONTH(GETDATE());
IF #mon <10
set #stringMon ='0' + CONVERT(VARCHAR(1),#mon) ;
ELSE
set #stringMon = CONVERT(VARCHAR(2),#mon) ;
IF #maxOrderID is null --no orders has been added in this month:
begin
set #maxOrderRef = Substring(CONVERT(VARCHAR(4),YEAR(GETDATE())),3,4)+ '-'+ CONVERT(VARCHAR(2),#stringMon)+'-001';
end
ELSE
--custom order id format (always XXX):
begin
set #relativeID =(SELECT [purchaseOrderRef] FROM [Products_SumOrders] WHERE orderid=#maxOrderID);
set #relativeID = Substring(#relativeID,LEN(#relativeID)-(Charindex('-', REVERSE(#relativeID))-2),LEN(#relativeID));
print(CONVERT(int,#relativeID));
IF CONVERT(int,#relativeID) < 9
set #relativeID ='00' + CONVERT(VARCHAR(2),#relativeID+1) ;
ELSE
begin
if CONVERT(int,#relativeID) < 99
set #relativeID ='0' + CONVERT(VARCHAR(3),#relativeID+1) ;
else
set #relativeID = CONVERT(VARCHAR(3),#relativeID+1) ;
end
set #maxOrderRef = Substring(CONVERT(VARCHAR(4),YEAR(GETDATE())),3,4)+ '-'+ CONVERT(VARCHAR(2),#stringMon)+'-'+ CONVERT(VARCHAR(3),#relativeID);
end
print(#maxOrderRef);
UPDATE Products_SumOrders
SET purchaseOrderRef = #maxOrderRef
FROM inserted INNER JOIN [Products_SumOrders] On inserted.orderid = [Products_SumOrders].orderid
END
GO
Related
I am running a MySQL Query. But when a new row is added from form input I get this error:
Error: Can't update table 'brandnames' in stored function/trigger because it is
already used by statement which invoked this stored function/trigger.
From the code:
CREATE TRIGGER `capital` AFTER INSERT ON `brandnames`
FOR EACH
ROW UPDATE brandnames
SET bname = CONCAT( UCASE( LEFT( bname, 1 ) ) , LCASE( SUBSTRING( bname, 2 ) ) )
What does this error mean?
You cannot change a table while the INSERT trigger is firing. The INSERT might do some locking which could result in a deadlock. Also, updating the table from a trigger would then cause the same trigger to fire again in an infinite recursive loop. Both of these reasons are why MySQL prevents you from doing this.
However, depending on what you're trying to achieve, you can access the new values by using NEW.fieldname or even the old values --if doing an UPDATE-- with OLD.
If you had a row named full_brand_name and you wanted to use the first two letters as a short name in the field small_name you could use:
CREATE TRIGGER `capital` BEFORE INSERT ON `brandnames`
FOR EACH ROW BEGIN
SET NEW.short_name = CONCAT(UCASE(LEFT(NEW.full_name,1)) , LCASE(SUBSTRING(NEW.full_name,2)))
END
The correct syntax is:
FOR EACH ROW SET NEW.bname = CONCAT( UCASE( LEFT( NEW.bname, 1 ) )
, LCASE( SUBSTRING( NEW.bname, 2 ) ) )
A "BEFORE-INSERT"-trigger is the only way to realize same-table updates on an insert, and is only possible from MySQL 5.5+. However, the value of an auto-increment field is only available to an "AFTER-INSERT" trigger - it defaults to 0 in the BEFORE-case. Therefore the following example code which would set a previously-calculated surrogate key value based on the auto-increment value id will compile, but not actually work since NEW.id will always be 0:
create table products(id int not null auto_increment, surrogatekey varchar(10), description text);
create trigger trgProductSurrogatekey before insert on product
for each row set NEW.surrogatekey =
(select surrogatekey from surrogatekeys where id = NEW.id);
#gerrit_hoekstra wrote: "However, the value of an auto-increment field is only available to an "AFTER-INSERT" trigger - it defaults to 0 in the BEFORE-case."
That is correct but you can select the auto-increment field value that will be inserted by the subsequent INSERT quite easily. This is an example that works:
CREATE DEFINER = CURRENT_USER TRIGGER `lgffin`.`variable_BEFORE_INSERT` BEFORE INSERT
ON `variable` FOR EACH ROW
BEGIN
SET NEW.prefixed_id = CONCAT(NEW.fixed_variable, (SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'lgffin'
AND TABLE_NAME = 'variable'));
END
I have the same problem and fix by add "new." before the field is updated. And I post full trigger here for someone to want to write a trigger
DELIMITER $$
USE `nc`$$
CREATE
TRIGGER `nhachung_province_count_update` BEFORE UPDATE ON `nhachung`
FOR EACH ROW BEGIN
DECLARE slug_province VARCHAR(128);
DECLARE slug_district VARCHAR(128);
IF old.status!=new.status THEN /* neu doi status */
IF new.status="Y" THEN
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id;
ELSE
UPDATE province SET `count`=`count`-1 WHERE id = new.district_id;
END IF;
ELSEIF old.province_id!=new.province_id THEN /* neu doi province_id + district_id */
UPDATE province SET `count`=`count`+1 WHERE id = new.province_id; /* province_id */
UPDATE province SET `count`=`count`-1 WHERE id = old.province_id;
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id; /* district_id */
UPDATE province SET `count`=`count`-1 WHERE id = old.district_id;
SET slug_province = ( SELECT slug FROM province WHERE id= new.province_id LIMIT 0,1 );
SET slug_district = ( SELECT slug FROM province WHERE id= new.district_id LIMIT 0,1 );
SET new.prov_dist_url=CONCAT(slug_province, "/", slug_district);
ELSEIF old.district_id!=new.district_id THEN
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id;
UPDATE province SET `count`=`count`-1 WHERE id = old.district_id;
SET slug_province = ( SELECT slug FROM province WHERE id= new.province_id LIMIT 0,1 );
SET slug_district = ( SELECT slug FROM province WHERE id= new.district_id LIMIT 0,1 );
SET new.prov_dist_url=CONCAT(slug_province, "/", slug_district);
END IF;
END;
$$
DELIMITER ;
Hope this help someone
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
I need some help about triggers. I’m currently developing a platform and a database in order to manage exams at my university. Here is my problem:
I have 1 supertype table, which contains all the persons registered on the platform. I have to be able to make the distinction for each person between the functions “Candidate” and “Examiner”. So I have my 2 subtype tables, one for all the candidates and one for all the examiners. To achieve that, I’m using insert triggers.
In addition, a person can be both Candidate and Examiner, but not at the same time. So after updating the supertype table, I also need a trigger to be able to delete a specific row from one of the two-subtype table and insert the user information on the other.
Here is a simplified design of these 3 tables:
My INSERT trigger :
ALTER TRIGGER [dbo].[role_insert]
ON [dbo].[alemp_persons]
FOR INSERT
AS
DECLARE #random_number int
SELECT #random_number = CAST(CAST(rand() as binary(2)) as int)
BEGIN
INSERT INTO dbo.alemp_candidates
(
id_person, random_number
)
SELECT id_person, # random_number
FROM INSERTED
WHERE function='Candidate'
INSERT INTO dbo.alemp_examiners
(
id_person
)
SELECT id_person
FROM INSERTED
Where function='Examiner'
END
GO
My UPDATE trigger :
ALTER TRIGGER [dbo].[role_update] ON [dbo].[alemp_persons]
AFTER UPDATE
AS
DECLARE #id_person int
DECLARE #newFunction int SELECT #newFunction=function FROM inserted
DECLARE #random_number int SELECT # random_number = CAST(CAST(rand() as binary(2)) as int)
IF #newFunction = 'Candidate'
BEGIN
DELETE
FROM dbo.alemp_examiners
WHERE id_person=#id_person
END
BEGIN
SET IDENTITY_INSERT dbo.alemp_candidates ON;
INSERT INTO dbo.alemp_candidates
(
id_person, random_number
)
SELECT #id_person, random_number
SET IDENTITY_INSERT dbo.alemp_candidates OFF;
END
IF #newFunction = 'Examiner'
BEGIN
DELETE
FROM dbo.alemp_candidates
WHERE id_person=#id_person
END
BEGIN
SET IDENTITY_INSERT dbo.alemp_examiners ON;
INSERT INTO dbo.alemp_examiners
(
id_person
)
SELECT #id_person
SET IDENTITY_INSERT dbo.alemp_examiners Off;
END
GO
As I said above, my INSERT trigger works as I want. However when I want to update the function of one person, I got an error :
Explicit value must be specified for identity column either when IDENTITY_INSERT is set
to ON or when a replication user is inserting into a NOT FOR REPLICATION identity column.
Some simple notes:
1) You should follow Mitch Wheat's advice and rewrite these triggers because inserted and deleted tables could have more than one row. For example, your trigger will have a bad behavior when is executed the next statement UPDATE [dbo].[alemp_persons] SET function = CASE WHEN id_person = 1 THEN 'Candidate' ELSE 'Examiner' END WHERE id_person IN (1,2) if the first person's function is 'Examiner' and the second person's function is 'Candidate'.
2) [dbo].[alemp_persons].function's data type should be [tiny]int or char(1) and not varchar(something greater than 1) (Where function='Examiner').
3) [dbo].[alemp_persons].function column should disallow Nulls.
4) [dbo].[alemp_persons].function column should has a CHECK constraint:
ALTER TABLE [dbo].[alemp_persons]
ADD CONSTRAINT CK_alemp_persons_function_Verify CHECK ( function IN ('Candidate', 'Examiner') );
5) It would be nice to add
a function column to [dbo].[alemp_candidates] and [dbo].[alemp_examiners] tables,
two check constraints on [dbo].[alemp_candidates] (function = 'Candidate') and [dbo].[alemp_examiners] (function = 'Examiner'),
an UNIQUE index on [dbo].[alemp_persons](id_person, function),
two FKs between [dbo].[alemp_candidates/examiners](id_person, function) and [dbo].[alemp_persons](id_person, function).
This way, you can be sure that [dbo].[alemp_candidates] table has only candidates and [dbo].[alemp_examiners] has only examiners and every person can be only candidate or examiner at one time.
6) You should disallow IDENTITY property for id_person columns in [dbo].[alemp_candidates] and [dbo].[alemp_examiners] table (SET IDENTITY_INSERT dbo.alemp_candidates ...).
8) And this statement IF #newFunction = 'Candidate' should raise an error because #newFunction data type is 'INT'.
9) And the AFTER UPDATE trigger on [dbo].[alemp_persons] table will move data between candidates and examiners tables (not tested):
ALTER TRIGGER [dbo].[role_update]
ON [dbo].[alemp_persons]
FOR UPDATE
AS
BEGIN
DECLARE #selected_rows TABLE (
id_person INT PRIMARY KEY, -- or BIGINT, look at alemp_person.id_person data type
new_function VARCHAR(50) NOT NULL -- look at alemp_person.function column data type
);
INSERT #selected_rows (id_person, new_function)
SELECT new.id_person, new.function
FROM inserted as new INNER JOIN deleted as old ON new.id_person = old.id_person
WHERE new.function <> old.function;
MERGER dbo.alemp_candidates AS dest
USING #selected_rows AS src ON dest.id_person = src.id_person
WHEN MATCHED THEN
DELETE
WHEN NOT MATCHED BY TARGET AND src.new_function = 'Candidate' THEN
INSERT (id_person, random_number)
VALUES (src.id_person, CONVERT(BINARY(2), CHECKSUM(NEWID()));
MERGER dbo.alemp_examiners AS dest
USING #selected_rows AS src ON dest.id_person = src.id_person
WHEN MATCHED THEN
DELETE
WHEN NOT MATCHED BY TARGET AND src.new_function = 'Examiner' THEN
INSERT (id_person)
VALUES (src.id_person);
END
I'm trying to generate a primary key for my table, something like this
(simplified version) - the purpose is to have a daily incremented key:
DELIMITER ^
CREATE TABLE `ADDRESS` (
ID INTEGER NOT NULL DEFAULT -1,
NAME VARCHAR(25),
PRIMARY KEY(`ID`))^
CREATE FUNCTION `GETID`()
RETURNS INTEGER
deterministic
BEGIN
declare CURR_DATE DATE;
declare maxid, _year, _month, _day, newid INTEGER;
set CURR_DATE = CURRENT_DATE;
set _year = EXTRACT(YEAR FROM CURR_DATE);
set _mon = EXTRACT(MONTH FROM CURR_DATE);
set _day = EXTRACT(DAY FROM CURR_DATE);
set newid = (_year - (_year/100) * 100) * 10000 + _mon * 100 + _day;
select max(ID) into maxid From `ADDRESS`;
if (maxid is null) then
set maxid = 0;
end if;
if (MAXID / 1000 != newid) then
set MAXID = newid * 1000;
end if;
set MAXID = MAXID + 1;
return MAXID;
END^
CREATE TRIGGER `ADDRESS_ID_TRIGGER` BEFORE INSERT ON `ADDRESS`
FOR EACH ROW
BEGIN
if new.id=-1 then
set new.id = getid();
end if ;
END^
COMMIT^
DELIMITER ;
Generally it works fine, but when I test it with multiple inserts at the same time
it obviously fails (e.g. no dirty reads, the select max will fail for the 2nd insert,
thus it will generate the same id as fro the 1st insert).
Workaround:
Make primary key AUTO_INCREMENT.
Add TIMESTAMP field and use BEFORE INSERT/UPDATE trigget to set CURRENT_TIMESTAMP().
Also you can use ON UPDATE CURRENT_TIMESTAMP option for TIMESTAMP field, value will be updated automatically.
So, ID is ID, and TIMESTAMP field contains date and time.
I want to generate PK through trigger as it is custom PK.
It is like depending on the member type field, I want to generate member id which is PK.
e.g. if new record's member type is DGIA, then member id will be DGIA1, DGIA2, DGIA3 ...and so on... if member type is DGIL, then member id will be DGIL1, DGIL2, DGIL3 ...and so on...
So, how to write trigger for the same... I have tried as following but it is working for 1st record only.
ALTER TRIGGER [dbo].[next_member_id] ON [dbo].[DAD_MEMBERSHIP] AFTER INSERT
AS
BEGIN
DECLARE #COUNT INT
SET #COUNT=0;
SELECT #COUNT=ISNULL(MAX(CAST(SUBSTRING(DAD_MEMBERSHIP.MEMBER_ID,5,15) AS INT)),0)+1 FROM DAD_MEMBERSHIP where DAD_MEMBERSHIP.MEMBER_TYPE = DAD_MEMBERSHIP.MEMBER_TYPE
update DAD_MEMBERSHIP set DAD_MEMBERSHIP.MEMBER_ID = DAD_MEMBERSHIP.MEMBER_TYPE + CONVERT(varchar,#COUNT)
from DAD_MEMBERSHIP inner join inserted on DAD_MEMBERSHIP.MEMBER_TYPE = inserted.MEMBER_TYPE
END
Triggers operate by batch of records, you cannot assign to a scalar variable and expect it to work for more than one record. You need to rethink your whole process into a set-based process.
I solved the problem using following trigger
ALTER TRIGGER [dbo].[next_member_id]
ON [dbo].[DAD_MEMBERSHIP]
AFTER INSERT
AS
BEGIN
DECLARE #COUNT INT
SET #COUNT=0;
DECLARE #STR VARCHAR(5)
SET #STR=''
select #STR=i.MEMBER_TYPE from inserted i;
SELECT #COUNT=ISNULL(MAX(CAST(SUBSTRING(DAD_MEMBERSHIP.MEMBER_ID,5,15) AS INT)),0)+1
from DAD_MEMBERSHIP where MEMBER_TYPE=#STR
update DAD_MEMBERSHIP set DAD_MEMBERSHIP.MEMBER_ID = #STR + CONVERT(varchar,#COUNT)
from DAD_MEMBERSHIP inner join inserted i on i.MEMBER_TYPE=DAD_MEMBERSHIP.MEMBER_TYPE where DAD_MEMBERSHIP.MEMBER_ID is null
END