nickoarg
asked on
Is this correct?
Hi, This is difficult for me since I know very little about triggers, tables and Databases in general. But... as sometimes happens during my job I've been assigned something out of my league. Now... I've been reading and trying to "reuse" examples to do what I'm trying to do.
So, let me first explain what I'm trying to do. We have this application that runs on Solaris and uses Syabase. The user ID's are defined on a Sybase table (adb.tssuser) and on the Sun OS. I have this software that can automatically create records on both, but just that. So, I can add a user on Solaris and create a home directory. Then I can insert a record on a sybase table. What this software can't do is execute scripts or do file system operations. So, what I have in mind is that after succesfull creation on the OS and on this intermediate table a trigger would trigger and run a script that would do the rest. The script has to be called with the userid and the cat fields added. Keep in mind that I'll be writing to a intermediate table and then, with a trigger, updating the definitve table (adb.tssuser). This is what I've come up to:
USE db
SET CHAINED OFF
CREATE TABLE emp
(
empno NUMERIC(8) IDENTITY,
usrid NVARCHAR(64) NULL,
cat CHAR(64) NULL,
CONSTRAINT pk_empno PRIMARY KEY (empno),
)
GO
/* holds last generated identity value */
CREATE TABLE empno
(
empno NUMERIC(8) NOT NULL,
CONSTRAINT unq_empno UNIQUE (empno)
)
INSERT INTO empno VALUES(-1)
GO
CREATE PROCEDURE sp_empno
@io_empno NUMERIC OUTPUT,
@i_userid VARCHAR
AS
DECLARE @key NUMERIC(8)
IF (@io_empno IS NULL)
BEGIN
DECLARE rs CURSOR FOR SELECT empno FROM empno
OPEN rs
FETCH rs INTO @key
IF(@key = -1)
SELECT @io_empno = NULL
ELSE
SELECT @io_empno = @key
CLOSE rs
DEALLOCATE CURSOR rs
END
GO
sp_procxmode sp_empno, "anymode"
GO
/************************* ********** ********** ********** ********** ********** */
/* Create event log table. */
/************************* ********** ********** ********** ********** ********** */
CREATE TABLE eventlog
(
record_id NUMERIC(38) IDENTITY
NOT NULL,
table_key VARCHAR(64) NOT NULL,
status CHAR(1) DEFAULT 'N',
event_type NUMERIC(1) NOT NULL
CHECK (event_type IN (1, 2, 3, 4, 5, 6, 7, 8)),
event_time DATETIME DEFAULT getDate()
NOT NULL,
perpetrator VARCHAR(64) DEFAULT USER
NULL,
table_name VARCHAR(64) NOT NULL,
column_name VARCHAR(64) NULL,
old_value NVARCHAR(64) NULL,
new_value NVARCHAR(64) NULL
)
CREATE UNIQUE NONCLUSTERED INDEX i_eventlog_1 ON eventlog(table_key, record_id, status)
CREATE UNIQUE NONCLUSTERED INDEX i_eventlog_2 ON eventlog(record_id, table_key)
GO
CREATE TRIGGER t_emp_insert
ON emp
FOR INSERT
AS
DECLARE
@opcode SMALLINT,
@date_style SMALLINT,
@table_name VARCHAR(64),
@key VARCHAR(64),
@new_empno VARCHAR(64)
UPDATE empno SET empno = (SELECT new.empno FROM inserted new)
SELECT @opcode = 5 /* Insert (Query-Back) */
SELECT @date_style = 109 /* mon dd yyy hh:mm:sss AM (or PM) */
SELECT @table_name = 'emp'
SELECT @new_empno = LTRIM(STR(new.empno)) from inserted new
SELECT @key = "empno=" + @new_empno
INSERT INTO dbo.eventlog(event_type, table_name, table_key)
VALUES(@opcode, @table_name, @key)
GO
CREATE TRIGGER t_emp_delete
ON emp
FOR DELETE
AS
INSERT INTO dbo.eventlog(event_type, table_name, table_key)
(SELECT 4, 'emp', 'empno=' + LTRIM(STR(old.empno)) from deleted old)
GO
CREATE TRIGGER t_emp_scp_add
ON emp
FOR INSERT
AS
DECLARE
@opcode SMALLINT,
@date_style SMALLINT,
@table_name VARCHAR(64),
@key VARCHAR(64),
@new_empno VARCHAR(64)
SELECT @opcode = 5 /* Insert (Query-Back) */
SELECT @date_style = 109 /* mon dd yyy hh:mm:sss AM (or PM) */
SELECT @table_name = 'emp'
SELECT @new_empid = STR(new.userid) from inserted new
SELECT @categ = STR(new.cat) from inserted new
select @script = "/home/nvl/oss_novell.sh " + @new_empid + " " + @categ
execute xp_cmdshell @script
GO
Thanks for your help!!!
Nico
So, let me first explain what I'm trying to do. We have this application that runs on Solaris and uses Syabase. The user ID's are defined on a Sybase table (adb.tssuser) and on the Sun OS. I have this software that can automatically create records on both, but just that. So, I can add a user on Solaris and create a home directory. Then I can insert a record on a sybase table. What this software can't do is execute scripts or do file system operations. So, what I have in mind is that after succesfull creation on the OS and on this intermediate table a trigger would trigger and run a script that would do the rest. The script has to be called with the userid and the cat fields added. Keep in mind that I'll be writing to a intermediate table and then, with a trigger, updating the definitve table (adb.tssuser). This is what I've come up to:
USE db
SET CHAINED OFF
CREATE TABLE emp
(
empno NUMERIC(8) IDENTITY,
usrid NVARCHAR(64) NULL,
cat CHAR(64) NULL,
CONSTRAINT pk_empno PRIMARY KEY (empno),
)
GO
/* holds last generated identity value */
CREATE TABLE empno
(
empno NUMERIC(8) NOT NULL,
CONSTRAINT unq_empno UNIQUE (empno)
)
INSERT INTO empno VALUES(-1)
GO
CREATE PROCEDURE sp_empno
@io_empno NUMERIC OUTPUT,
@i_userid VARCHAR
AS
DECLARE @key NUMERIC(8)
IF (@io_empno IS NULL)
BEGIN
DECLARE rs CURSOR FOR SELECT empno FROM empno
OPEN rs
FETCH rs INTO @key
IF(@key = -1)
SELECT @io_empno = NULL
ELSE
SELECT @io_empno = @key
CLOSE rs
DEALLOCATE CURSOR rs
END
GO
sp_procxmode sp_empno, "anymode"
GO
/*************************
/* Create event log table. */
/*************************
CREATE TABLE eventlog
(
record_id NUMERIC(38) IDENTITY
NOT NULL,
table_key VARCHAR(64) NOT NULL,
status CHAR(1) DEFAULT 'N',
event_type NUMERIC(1) NOT NULL
CHECK (event_type IN (1, 2, 3, 4, 5, 6, 7, 8)),
event_time DATETIME DEFAULT getDate()
NOT NULL,
perpetrator VARCHAR(64) DEFAULT USER
NULL,
table_name VARCHAR(64) NOT NULL,
column_name VARCHAR(64) NULL,
old_value NVARCHAR(64) NULL,
new_value NVARCHAR(64) NULL
)
CREATE UNIQUE NONCLUSTERED INDEX i_eventlog_1 ON eventlog(table_key, record_id, status)
CREATE UNIQUE NONCLUSTERED INDEX i_eventlog_2 ON eventlog(record_id, table_key)
GO
CREATE TRIGGER t_emp_insert
ON emp
FOR INSERT
AS
DECLARE
@opcode SMALLINT,
@date_style SMALLINT,
@table_name VARCHAR(64),
@key VARCHAR(64),
@new_empno VARCHAR(64)
UPDATE empno SET empno = (SELECT new.empno FROM inserted new)
SELECT @opcode = 5 /* Insert (Query-Back) */
SELECT @date_style = 109 /* mon dd yyy hh:mm:sss AM (or PM) */
SELECT @table_name = 'emp'
SELECT @new_empno = LTRIM(STR(new.empno)) from inserted new
SELECT @key = "empno=" + @new_empno
INSERT INTO dbo.eventlog(event_type, table_name, table_key)
VALUES(@opcode, @table_name, @key)
GO
CREATE TRIGGER t_emp_delete
ON emp
FOR DELETE
AS
INSERT INTO dbo.eventlog(event_type, table_name, table_key)
(SELECT 4, 'emp', 'empno=' + LTRIM(STR(old.empno)) from deleted old)
GO
CREATE TRIGGER t_emp_scp_add
ON emp
FOR INSERT
AS
DECLARE
@opcode SMALLINT,
@date_style SMALLINT,
@table_name VARCHAR(64),
@key VARCHAR(64),
@new_empno VARCHAR(64)
SELECT @opcode = 5 /* Insert (Query-Back) */
SELECT @date_style = 109 /* mon dd yyy hh:mm:sss AM (or PM) */
SELECT @table_name = 'emp'
SELECT @new_empid = STR(new.userid) from inserted new
SELECT @categ = STR(new.cat) from inserted new
select @script = "/home/nvl/oss_novell.sh " + @new_empid + " " + @categ
execute xp_cmdshell @script
GO
Thanks for your help!!!
Nico
your triggers are written as if you will only ever be processing one row at a time (common mistake)
you should also know that xp_cmdshell can not be rolled back, so :
begin tran
insert into emp ...
rollback
will cal the /home/nvl/oss_novell.sh script but you won't have the row in te database
you should also know that xp_cmdshell can not be rolled back, so :
begin tran
insert into emp ...
rollback
will cal the /home/nvl/oss_novell.sh script but you won't have the row in te database
ASKER
The idea is that only one row at a time can be inserted, never more than 1 in one operation.
..."but you won't have the row in te database"...
Why? Does the trigger acts before the row is inserted in the table "emp"?
"begin tran
insert into emp ...
rollback"
please, note that I really don't know about databases... I've base all that on examples and existing code... where do I put that? how should it look to be correct?
thanks
..."but you won't have the row in te database"...
Why? Does the trigger acts before the row is inserted in the table "emp"?
"begin tran
insert into emp ...
rollback"
please, note that I really don't know about databases... I've base all that on examples and existing code... where do I put that? how should it look to be correct?
thanks
> The idea is that only one row at a time can be inserted, never more than 1 in one operation.
that idea might be OK for this week, but next month or next year or later, someone will insert more than one row and the triggers will not function as expected
to protect yourself (asssuming you don want to rewrite them), put the following code into the top of the triggers.
IF @@rowcount > 1
BEGIN
ROLLBACK TRIGGER WITH RAISERROR <put your error details here>
RETURN
END
> Why? Does the trigger acts before the row is inserted in the table "emp"?
the trigger does not act before the row is inserted, the rollback will force everything that was just inserted/updated/deleted to be undone, but you can not undo a execution of a unix script. This is a known limitation of the xp commands.
that idea might be OK for this week, but next month or next year or later, someone will insert more than one row and the triggers will not function as expected
to protect yourself (asssuming you don want to rewrite them), put the following code into the top of the triggers.
IF @@rowcount > 1
BEGIN
ROLLBACK TRIGGER WITH RAISERROR <put your error details here>
RETURN
END
> Why? Does the trigger acts before the row is inserted in the table "emp"?
the trigger does not act before the row is inserted, the rollback will force everything that was just inserted/updated/deleted to be undone, but you can not undo a execution of a unix script. This is a known limitation of the xp commands.
ASKER
"someone will insert more than one row and the triggers will not function as expected"
no..., the updates come from a software that updates only one row at a time, but I undestand what you say.
I still don't understand the rollback...
step 1, a new row is inserted in the table emp
step 2, the trigger t_emp_scp_add fires away and the xp_cmdshell would run my script
why do I want to remove new the row from table emp? (assuming that that is what rollback does)
no..., the updates come from a software that updates only one row at a time, but I undestand what you say.
I still don't understand the rollback...
step 1, a new row is inserted in the table emp
step 2, the trigger t_emp_scp_add fires away and the xp_cmdshell would run my script
why do I want to remove new the row from table emp? (assuming that that is what rollback does)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I am suprised:
- this question was not even pinged
- and no answer is actually marked as accepted
- this question was not even pinged
- and no answer is actually marked as accepted
ASKER