Oracle How to assign usernames - sql

How would I assign usernames for students using their initials followed by numbers that increment? I'm not sure how many students I have in my database and I would like their usernames to look like so "AC001, JD003 for example. And also, If the have similar initials I would like the username to continue incrementing in that order. For example "AC001" and "AC002"

You will need to use a trigger on BEFORE INSERT event and a sequence to implement this.
I will assume your table is as follows:
TABLE user
( userid VARCHAR2(100) -- PRIMARY KEY COLUMN
, firstname VARCHAR2(100)
, lastname VARCHAR2(100)
, .... -- Other columns
);
Create a sequence as follows:
CREATE SEQUENCE sq_userid;
You insert rows with userid column set to null.
INSERT INTO user VALUES (null, 'Jack', 'Daniels', ....);
Then, your trigger should look like this:
CREATE OR REPLACE TRIGGER trg_user
BEFORE INSERT ON user
REFERENCING new AS new old AS old
FOR EACH ROW
BEGIN
IF :new.userid IS NULL THEN
:new.userid := UPPER(LEFT(firstname, 1))
|| UPPER(LEFT(lastname, 1))
|| TO_CHAR(sq_userid.nextval, '099');
END IF;
END;
/
The trigger will put 'JD001' AS the value for userid in this instance.
For more information- Coding triggers, sequences and to_char.

i think this will also work
1st Create sequence user_seq;
insert into user values('user_name'||user_seq.nextval);
you can modify above query as per your requirement.

I fiddled a solution, but it's in MySQL. I'm sure you can get the general idea and convert it into Oracle (there's an Oracle 11g option in SQL Fiddle itself): http://sqlfiddle.com/#!2/e8ed5/1
Schema:
CREATE TABLE ALPHA_ROLL (
ALPHA1 CHAR(1),
ALPHA2 CHAR(1),
ROLL INTEGER,
PRIMARY KEY(ALPHA1, ALPHA2)
)//
CREATE TABLE user (
USERID VARCHAR(5),
FIRSTNAME VARCHAR(100),
LASTNAME VARCHAR(100),
PRIMARY KEY (USERID)
)//
CREATE TRIGGER trg_user
BEFORE INSERT ON user
FOR EACH ROW
BEGIN
SET #gen_user_id =
(SELECT CONCAT(ALPHA1,ALPHA2,LPAD((ROLL+1), 3, '0'))
FROM ALPHA_ROLL
WHERE ALPHA1 = UPPER(LEFT(NEW.firstname, 1))
AND ALPHA2 = UPPER(LEFT(NEW.lastname, 1))
LIMIT 1);
IF (#gen_user_id IS NULL) THEN
INSERT INTO ALPHA_ROLL (ALPHA1, ALPHA2, ROLL)
VALUES (UPPER(LEFT(new.firstname, 1)), UPPER(LEFT(new.lastname, 1)), 1);
SET #GEN_USER_ID =
CONCAT(UPPER(LEFT(new.firstname, 1)),
UPPER(LEFT(new.lastname, 1)),
'001');
ELSE
UPDATE ALPHA_ROLL SET ROLL = ROLL + 1
WHERE ALPHA1 = UPPER(LEFT(new.firstname, 1))
AND ALPHA2 = UPPER(LEFT(new.lastname, 1));
END IF;
SET new.userid = #GEN_USER_ID;
END//
SQL:
INSERT INTO USER (FIRSTNAME, LASTNAME) VALUES ('Johnnie', 'Walker');
INSERT INTO USER (FIRSTNAME, LASTNAME) VALUES ('Jason', 'Mraz');
INSERT INTO USER (FIRSTNAME, LASTNAME) VALUES ('Mariah', 'Carrie');
INSERT INTO USER (FIRSTNAME, LASTNAME) VALUES ('Justin', 'Morg');
INSERT INTO USER (FIRSTNAME, LASTNAME) VALUES ('Matthew', 'Congoman');
INSERT INTO USER (FIRSTNAME, LASTNAME) VALUES ('Jack', 'Waltson');
INSERT INTO USER (FIRSTNAME, LASTNAME) VALUES ('Jojo', 'Wonderful');
SELECT * FROM USER;
SELECT * FROM ALPHA_ROLL;
Result:
USERID FIRSTNAME LASTNAME
JM001 Jason Mraz
JM002 Justin Morg
JW001 Johnnie Walker
JW002 Jack Waltson
JW003 Jojo Wonderful
MC001 Mariah Carrie
MC002 Matthew Congoman
ALPHA1 ALPHA2 ROLL
J M 2
J W 3
M C 2

Related

How to create a constraint for conditional unique values?

I am using SQL Server. I have this table:
CREATE TABLE Student
(
ID int PRIMARY KEY,
FirstName varchar(100),
LastName varchar(100),
Active bit;
)
I want to have unique(FirstName, LastName) students only if Active = 1. If they are inactive, unique constraint should not trigger. Any idea?
You can't create a CONSTRAINT for that, however, you can create a filtered unique index:
USE Sandbox;
GO
CREATE TABLE dbo.Student (ID int IDENTITY(1, 1) PRIMARY KEY,
FirstName varchar(100),
LastName varchar(100),
Active bit);
CREATE UNIQUE INDEX UQ_StudentName
ON Student (FirstName,LastName)
WHERE Active = 1;
GO
INSERT INTO dbo.Student (FirstName,
LastName,
Active)
VALUES ('Jane', 'Smith', 1); --Success
GO
INSERT INTO dbo.Student (FirstName,
LastName,
Active)
VALUES ('Jane', 'Smith', 0); --Success
GO
INSERT INTO dbo.Student (FirstName,
LastName,
Active)
VALUES ('Jane', 'Smith', 0); --Success
GO
INSERT INTO dbo.Student (FirstName,
LastName,
Active)
VALUES ('Jane', 'Smith', 1); --Fails;
GO
UPDATE dbo.Student
SET Active = 1
WHERE ID = 2; --Fails;
GO
SELECT *
FROM dbo.Student;
GO
DROP TABLE dbo.Student;
I however, highly recommend against the thought that names are unique. I (personally) shared my name and date of birth with another person at several places in my youth and businesses that treated names (and date of birth) as unique on their systems were such a head ache for the both of us (there really were places where I (or they) couldn't register without using an abbreviated name because we "already existed").
Create a filtered unique index:
CREATE UNIQUE INDEX UNI_Student_FirstName_LastName ON Student (FirstName, LastName)
WHERE Active = 1

postgresql - use just created identity value to return newly inserted row

Using SQL Server I can write the following statement...
create table Person(
id int identity(1,1),
name varchar(50)
)
insert into Person(name) values ('John')
select * from Person where id = scope_identity()
In Postgres I can do this:
CREATE TABLE public.Person
(
id serial primary key,
name character varying(10) NOT NULL
)
INSERT INTO Person(name) VALUES ('Smith', 'John') RETURNING id;
How would I write an equivalent statement like I did in the SQL example where don't return the id, but the entire row that was just inserted?
As #cur4so stated, or alternatively
INSERT INTO Person(name) VALUES ('Smith', 'John') RETURNING *;
INSERT INTO Person (name) VALUES ('Smith John');
select * from Person where id = currval('person_id_seq');

Insert into a Informix table or update if exists

I want to add a row to an Informix database table, but when a row exists with the same unique key I want to update the row.
I have found a solution for MySQL here which is as follows but I need it for Informix:
INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE name="A", age=19
You probably should use the MERGE statement.
Given a suitable table:
create table table (id serial not null primary key, name varchar(20) not null, age integer not null);
this SQL works:
MERGE INTO table AS dst
USING (SELECT 1 AS id, 'A' AS name, 19 AS age
FROM sysmaster:'informix'.sysdual
) AS src
ON dst.id = src.id
WHEN NOT MATCHED THEN INSERT (dst.id, dst.name, dst.age)
VALUES (src.id, src.name, src.age)
WHEN MATCHED THEN UPDATE SET dst.name = src.name, dst.age = src.age
Informix has interesting rules allowing the use of keywords as identifiers without needing double quotes (indeed, unless you have DELIMIDENT set in the environment, double quotes are simply an alternative to single quotes around strings).
You can try the same behavior using the MERGE statement:
Example, creation of the target table:
CREATE TABLE target
(
id SERIAL PRIMARY KEY CONSTRAINT pk_tst,
name CHAR(1),
age SMALLINT
);
Create a temporary source table and insert the record you want:
CREATE TEMP TABLE source
(
id INT,
name CHAR(1),
age SMALLINT
) WITH NO LOG;
INSERT INTO source (id, name, age) VALUES (1, 'A', 19);
The MERGE would be:
MERGE INTO target AS t
USING source AS s ON t.id = s.id
WHEN MATCHED THEN
UPDATE
SET t.name = s.name, t.age = s.age
WHEN NOT MATCHED THEN
INSERT (id, name, age)
VALUES (s.id, s.name, s.age);
You'll see that the record was inserted then you can:
UPDATE source
SET age = 20
WHERE id = 1;
And test the MERGE again.
Another way to do it is create a stored procedure, basically you will do the INSERT statement and check the SQL error code, if it's -100 you go for the UPDATE.
Something like:
CREATE PROCEDURE sp_insrt_target(v_id INT, v_name CHAR(1), v_age SMALLINT)
ON EXCEPTION IN (-100)
UPDATE target
SET name = v_name, age = v_age
WHERE id = v_id;
END EXCEPTION
INSERT INTO target VALUES (v_id, v_name, v_age);
END PROCEDURE;

How to pass an array of numbers to a stored procedure?

I would like to write a stored procedure that can receive one or more employee IDs and return data based on these IDs. The number of employee IDs will vary every time the sproc is called.
How can I write a the stored procedure to return the Branch Address of every employee ID passed in, where the number of employee IDs will be variable?
Employee Table
ID
Name
Branch_ID
Branch Table
ID
Name
Address
If you have an SQL 2008 or higher running then I'd suggest using table types. Then you can pass a table to the stored procedure. Here is a little example I made to demonstrate just that.
create database tmpDB;
go
use tmpDB;
go
create table tblEmployee
(
ID int identity(1, 1)
primary key
not null,
Name nvarchar(200),
Branch_ID int
);
go
insert into dbo.tblEmployee
(Name, Branch_ID)
values (N'Brian', 1),
(N'Mary', 1),
(N'Peter', 2),
(N'Sonya', 2),
(N'Roland', 1),
(N'Tom', 3),
(N'Sam', 3),
(N'Ryan', 3),
(N'Julia', 3),
(N'Tim', 1),
(N'Eva', 2);
go
select *
from dbo.tblEmployee;
go
create type typEmployee as table
(
Name nvarchar(200),
BranchID int
);
go
grant exec on type::typEmployee to public;
go
create procedure spInsertEmployees
(
#NewEmployees typEmployee readonly
)
as
begin
merge tblEmployee as target
using
(
select Name,
BranchID
from #NewEmployees
) as source (Name, BranchID)
on (
target.Name = source.Name
and target.Branch_ID = source.BranchID
)
when not matched then
insert (Name, Branch_ID)
values (
source.Name,
source.BranchID
);
end;
go
grant execute on spInsertEmployees to public;
go
declare #tmpTable typEmployee;
insert into #tmpTable
(Name, BranchID)
values (N'NewEmployee', 1),
(N'NewEmployee', 2),
(N'NewEmployee', 3),
(N'Sonya', 2),
(N'Tim', 1);
exec dbo.spInsertEmployees
#NewEmployees = #tmpTable;
select *
from dbo.tblEmployee;
go
use master;
go
drop database tmpDB;
go
What we do is just pass in a delimited list. So 1,2,3,42,55,6666 with nvarchar(max).
Then we have a user defined function that returns a table and we join on that.
Google search on t sql split string using delimiter and you'll find examples.
select * from dbo.udfSplit(#inputfromparameters, ",") inner join ....

SQL Server 2008 Before Insert Trigger

I have the following Query:
Insert into tblTest (ID, Name, Age) VALUES (1, 'TestName', 20);
In my trigger I want to check - if the query's ID is equal to 1, send another query:
Insert into tblTest (ID, Name, Age) VALUES (2, 'TestName', 21);
Else, dont do anything.
The problem is, I dont know how to keep the parameters as is and just change the age, so basically I want to send the SAME query, and change a certain parameter (in this case, its the age parameter).
The rows about to be inserted can be found in the special inserted table. Here's an example:
if object_id('tblTest') is not null
drop table tblTest
create table tblTest (id int, name varchar(50), age int)
go
create trigger trg_tblTest_BeforeInsert
on tblTest
after insert
as begin
insert tblTest
select id + 1
, name
, age + 1
from inserted
where id = 1 -- Only for rows with id=1
end
go
insert tblTest (id, name, age) values (1, 'TestName', 20)
select * from dbo.tblTest
This prints:
id name age
1 TestName 20
2 TestName 21