DB2 SQL Triggers - sql

I'm pretty new (like read-about-it-5-hours-ago-new) into Triggers, so I need some help on this:
Create the table TelefonnummerAenderung and delete all data in it if it already exists.
Create a Trigger meeting the following conditions: (I hope it's ok for you guys if I don't translate all the table names and attributes into English.)
-a change of the attribute Telefonnummer in KundenKontaktDaten is only allowed 15 secs after the last change
-otherwise a SIGNAL SQLSTATE '70001' is thrown
-while changing the Telefonnummer in KundenKontaktDaten a new entry in TelefonnummerAenderungen is created containing the old Telefonnummer and the time it was changed
-if the new and the old Telefonnummer are the same, no trigger action takes place
The two tables are the following:
KundenKontaktDaten: (edit: I forgot, Kunden_Nr is also referencing Kunde(Kunden_Nr). It should not matter for the task, just saying)
create table KundenKontaktDaten
( Kunden_Nr int not null primary key,
Twitter_Id Varchar(40),
Google_Id bigint,
Facebook_Id bigint,
Skype_Id Varchar(64),
Telefonnummer Varchar(50)
);
TelefonnummerAenderungen:
create table TelefonnummerAenderungen
( GEAENDERT_AM TIMESTAMP NOT NULL,
KUNDEN_NR INTEGER NOT NULL,
ALTE_NUMMER VARCHAR(50),
FOREIGN KEY(KUNDEN_NR)
REFERENCES KUNDE(KUNDEN_NR)
ON DELETE CASCADE
ON UPDATE RESTRICT,
PRIMARY KEY(GEAENDERT_AM, KUNDEN_NR)
);
My solution(java code; should not matter concerning the question):
static public void triggerAnlegen(Connection con) throws SQLException {
Statement stmt = con.createStatement();
try {
stmt.execute("create table TelefonnummerAenderungen ( GEAENDERT_AM TIMESTAMP NOT NULL, KUNDEN_NR INTEGER NOT NULL, ALTE_NUMMER VARCHAR(50), FOREIGN KEY(KUNDEN_NR) REFERENCES KUNDE(KUNDEN_NR) ON DELETE CASCADE ON UPDATE RESTRICT, PRIMARY KEY(GEAENDERT_AM, KUNDEN_NR))");
} catch (SQLException e) {
if(e.getErrorCode()==-601){
stmt.execute("DELETE FROM TelefonnummerAenderungen");
}
}
try{
stmt.execute("CREATE TRIGGER haTrigger AFTER UPDATE OF Telefonnummer ON KundenKontaktDaten REFERENCING NEW as n_row OLD as o_row FOR EACH ROW WHEN (o_row.Telefonnummer<>n_row.Telefonnummer) "+
"BEGIN " +
"IF(NOT EXISTS(SELECT * FROM TelefonnummerAenderungen WHERE Kunden_Nr=n_row.Kunden_Nr)) " +
"THEN " +
"INSERT INTO TelefonnummerAenderungen VALUES (CURRENT TIMESTAMP,n_row.Kunden_Nr,o_row.Telefonnummer); " +
"ELSEIF(CURRENT TIMESTAMP<((SELECT GEAENDERT_AM FROM TelefonnummerAenderungen WHERE Kunden_Nr=n_row.Kunden_Nr) + 15 seconds)) " +
"THEN " +
"UPDATE KundenKontaktDaten SET Kunden_Nr=o_row.Kunden_Nr,Twitter_Id=o_row.Twitter_Id,Google_Id=o_row.Google_Id,Facebook_Id=o_row.Facebook_Id,Skype_Id=o_row.Skype_Id,Telefonnummer=o_row.Telefonnummer;" +
"SIGNAL SQLSTATE '70001'; " +
"ELSE " +
"UPDATE TelefonnummerAenderungen SET GEAENDERT_AM=CURRENT TIMESTAMP,ALTE_NUMMER=o_row.Telefonnummer WHERE Kunden_Nr=n_row.Kunden_Nr; " +
"END IF;" +
"END");
} catch (SQLException e) {
throw e;
}
}
SQL-only:
CREATE TRIGGER haTrigger
AFTER UPDATE OF Telefonnummer ON KundenKontaktDaten
REFERENCING
NEW as n_row
OLD as o_row
FOR EACH ROW WHEN (o_row.Telefonnummer <> n_row.Telefonnummer)
BEGIN
IF (NOT EXISTS (SELECT *
FROM TelefonnummerAenderungen
WHERE Kunden_Nr=n_row.Kunden_Nr)
)
THEN
INSERT INTO TelefonnummerAenderungen
VALUES
(CURRENT TIMESTAMP, n_row.Kunden_Nr, o_row.Telefonnummer);
ELSEIF (CURRENT TIMESTAMP < ((SELECT GEAENDERT_AM
FROM TelefonnummerAenderungen
WHERE Kunden_Nr=n_row.Kunden_Nr) + 15 seconds)
)
THEN
UPDATE KundenKontaktDaten
SET Kunden_Nr = o_row.Kunden_Nr,
Twitter_Id = o_row.Twitter_Id,
Google_Id = o_row.Google_Id,
Facebook_Id = o_row.Facebook_Id,
Skype_Id = o_row.Skype_Id,
Telefonnummer = o_row.Telefonnummer;
SIGNAL SQLSTATE '70001';
ELSE
UPDATE TelefonnummerAenderungen
SET GEAENDERT_AM = CURRENT TIMESTAMP,
ALTE_NUMMER = o_row.Telefonnummer
WHERE Kunden_Nr = n_row.Kunden_Nr;
END IF;
END
I used the AFTER UPDATE OF [...] because I was not sure, whether (when using BEFORE UPDATE OF [...]) the query, which caused the trigger to trigger, is still being executed after the trigger handling .
[edit: changed it to BEFORE and dropped the
UPDATE KundenKontaktDaten
SET Kunden_Nr = o_row.Kunden_Nr,
Twitter_Id = o_row.Twitter_Id,
Google_Id = o_row.Google_Id,
Facebook_Id = o_row.Facebook_Id,
Skype_Id = o_row.Skype_Id,
Telefonnummer = o_row.Telefonnummer;
because I was getting cascading trigger errors otherwise ; won't change the code here though for matter of transparency]
This is (obviously) my homework (no real-world-problem, hope that's ok, and we get graded automatically by some test function we don't know - that way I know my results are wrong.
But I don't know which part of it is wrong, so I need some help on this.
Edit 2:
My post is getting kind of confusing, sorry. I thought creating an answer would be more clear than further editing of my post:
After further testing I figured out the problem with the first attempt:
When using 'AFTER UPDATE...' in my trigger, it's too late and I can't undo the changes made to 'KundenKontaktDaten' although the 15 seconds didn't pass, since it would result in cascading trigger calls.
When using 'BEFORE UPDATE...' DB2 restricts me of using any kind of INSERT or UPDATE.
So I figured out I have to use INSTEAD OF:
CREATE TRIGGER haTrigger INSTEAD OF UPDATE ON KundenKontaktDaten REFERENCING NEW as n_row OLD as o_row FOR EACH ROW
BEGIN
IF(o_row.Telefonnummer<>n_row.Telefonnummer) THEN
IF(NOT EXISTS(SELECT * FROM TelefonnummerAenderungen WHERE Kunden_Nr=n_row.Kunden_Nr)) THEN
UPDATE KundenKontaktDaten SET Kunden_Nr=n_row.Kunden_Nr,Twitter_Id=n_row.Twitter_Id,Google_Id=n_row.Google_Id,Facebook_Id=n_row.Facebook_Id,
Skype_Id=n_row.Skype_Id,Telefonnummer=n_row.Telefonnummer WHERE Kunden_Nr=o_row.Kunden_Nr;
INSERT INTO TelefonnummerAenderungen VALUES (CURRENT TIMESTAMP,n_row.Kunden_Nr,o_row.Telefonnummer);
ELSEIF(CURRENT TIMESTAMP<((SELECT GEAENDERT_AM FROM TelefonnummerAenderungen WHERE Kunden_Nr=n_row.Kunden_Nr) + 15 seconds)) THEN
SIGNAL SQLSTATE '70001';
ELSE
UPDATE KundenKontaktDaten SET Kunden_Nr=n_row.Kunden_Nr,Twitter_Id=n_row.Twitter_Id,Google_Id=n_row.Google_Id,Facebook_Id=n_row.Facebook_Id,
Skype_Id=n_row.Skype_Id,Telefonnummer=n_row.Telefonnummer WHERE Kunden_Nr=o_row.Kunden_Nr;
UPDATE TelefonnummerAenderungen SET GEAENDERT_AM=CURRENT TIMESTAMP,ALTE_NUMMER=o_row.Telefonnummer WHERE Kunden_Nr=n_row.Kunden_Nr;
END IF;
END IF;
END
resulting in yet another error:
DB2 SQL Error: SQLCODE=-159, SQLSTATE=42809,
SQLERRMC=GRP13.KUNDENKONTAKTDATEN;TABLE;UNTYPED VIEW
Since I have no idea, does anyone know what's the problem with that one? If neither Before nor After nor Instead of works, then I'm kind of running out of options.

I don't think you need to include the UPDATE of KundenKontaktDaten in the trigger, because the table is already modified by the statement that invokes the trigger. It probably should look somewhat like this:
CREATE TRIGGER haTrigger
AFTER UPDATE OF Telefonnummer ON KundenKontaktDaten
REFERENCING NEW as n_row OLD as o_row
FOR EACH ROW
WHEN (o_row.Telefonnummer<>n_row.Telefonnummer)
BEGIN
IF EXISTS (
SELECT 1 FROM TelefonnummerAenderungen a
WHERE a.Kunden_Nr = o_row.Kunden_Nr
AND a.GEAENDERT_AM > CURRENT TIMESTAMP - 15 seconds
)
THEN -- within the 15 sec. window, record old telephone number
INSERT INTO TelefonnummerAenderungen
VALUES (CURRENT TIMESTAMP, o_row.Kunden_Nr,o_row.Telefonnummer);
ELSE -- too late
SIGNAL SQLSTATE '70001';
END IF;
END
PS. Not tested.
PPS. You probably should store GEAENDERT_AM also in KundenKontaktDaten to avoid the extra query.

Related

Triggering an Update a value after Insert and Delete operations?

I have an activity from my SQL Server class and I'm missing only this trigger to complete it.
My teacher has asked in this activity to do the following trigger operation on a column sequential on telefone table.
After an insert statement, always keep the values in sequence like the first record is 0, the next should be 1 and there it goes.
And for the delete statement if someone removes a record the sequential value should be reordered.
I've got the insert statement working fine creating a sequence and adding it's next value to the column.
But no lucky with the delete statement.
Here's what I have so far for the trigger:
CREATE TRIGGER tg_sequencial
ON Telefone
AFTER INSERT, UPDATE
AS
BEGIN
DECLARE #vSequencial_Ins INT, #vSequencial_Del INT
SELECT #vSequencial_Ins = inserted.Sequencial FROM inserted
SELECT #vSequencial_Del = deleted.Sequencial FROM deleted
-- Check if it is an insert operation
if(#vSequencial_Ins IS NOT NULL AND #vSequencial_Del IS NULL)
begin
update Telefone set Sequencial = NEXT VALUE FOR dbo.Sequencial
from Telefone tel
join inserted i on i.IdPessoa = tel.IdPessoa
end
-- Check if it is an delete operation
else if(#vSequencial_Ins IS NULL AND #vSequencial_Del IS NOT NULL)
begin
alter sequence dbo.Sequencial
restart with 0
end
end
And this is the sequence code:
CREATE SEQUENCE dbo.Sequencial
START WITH 0
INCREMENT BY 1
NO CACHE
;
GO
My telefone table has the following values:
Sequencial smallint not null [PK]
IdPessoa int not null[PFK],
IdTipoTelefone tinyint not null [FK],
NumeroTelefone int not null,
DDD tinyint not null
EDIT: Got insert trigger working fine after changing the code from:
update Telefone set Sequencial = NEXT VALUE FOR dbo.Sequencial
To:
update Telefone set Sequencial = NEXT VALUE FOR dbo.Sequencial
from Telefone tel
join inserted i on i.IdPessoa = tel.IdPessoa
It now affects just the selected row instead of increasing all the fields.

Use trigger after multiple insert to update log table

I have the following trigger:
ALTER TRIGGER [Staging].[tr_UriData_ForInsert]
ON [Staging].[UriData]
FOR INSERT
AS
BEGIN
DECLARE #_Serial NVARCHAR(50)
DECLARE #_Count AS INT
IF ##ROWCOUNT = 0
RETURN
SET NOCOUNT ON;
IF EXISTS(SELECT * FROM inserted)
BEGIN
SELECT #_Count = COUNT(Id) FROM inserted
SELECT #_Serial = SerialNumber FROM inserted
INSERT INTO [Staging].[DataLog]
VALUES (CURRENT_TIMESTAMP, #_Serial + ': Data Insert --> Rows inserted: ' + #_Count, 'New data has been received')
END
END
The table receives multiple rows at once. I want to be able to add one row in the log table to tell me the insert has happened.
It works great with one row being inserted, but with multiple rows, the trigger doesn't fire. I have read other items on here and it is quite clear that you shouldn't use ROW_NUMBER().
In summary: I want to update my log table when a multiple row insert happens in another table called UriData.
The data is inserted from C# using the following:
using (var sqlBulk = new SqlBulkCopy(conn, SqlBulkCopyOptions.Default, transaction))
{
sqlBulk.DestinationTableName = tableName;
try
{
sqlBulk.WriteToServer(dt);
}
catch(SqlException sqlEx)
{
transaction.Rollback();
var msg = sqlEx.Message;
return false;
}
finally {
transaction.Commit();
conn.Close();
}
}
I don't want to know what is being inserted, but when it has happened, so I can run a set of SPROCS to clean and pivot the data.
TIA
The problem is your trigger assumes that only one row will be updated. A scalar variable can only have 1 value. So, for example, the statement SELECT #_Serial = SerialNumber FROM inserted will set #_Serial with the last value returned from the object inserted.
Treat your data as what it is, a dataset. This is untested, however, I suspect this gives you the result you want:
ALTER TRIGGER [Staging].[tr_UriData_ForInsert]
ON [Staging].[UriData]
FOR INSERT
AS
BEGIN
--No need for a ROWCOUNT. If there are no rows, then nothing was inserted, and this trigger won't happen.
INSERT INTO [Staging].[DataLog] ({COLUMNS LIST})
SELECT CURRENT_TIMESTAMP,
SerialNumber + ': Data Insert --> Rows inserted: ' +
CONVERT(varchar(10),COUNT(SerialNumber) OVER (PARTITION BY SerialNumber)), --COUNT returns an INT, so this statement would have failed with a conversion error too
'New data has been received'
FROM inserted;
END
Please note my comments or sections in braces ({}).
Edit: Sean, who has since deleted his answer, used GROUP BY. I copied what exact method you had, however, GROUP BY might well be the clause you want, rather than OVER.
So after a lot of digging and arguing, my hosting company told me that they have disabled bulk inserts of any kind, without bothering to notify their customers.

How to ensure my SQL varchar field is unique

I'm sure this is really simple but I've been up through the night and am now getting stuck.
I have a piece of functionality that clones a record in a database however I need to ensure the new name field is unique in the database.
eg, the first record is
[ProjectName] [ResourceCount]
'My Project' 8
Then when I click the clone I want
'My Project Cloned', 8
But then if I hit the button again it should notice that the cloned name exists and rather spit out
'My Project Cloned 2', 8
Is that making sense?
I can do it with temp tables and cursors but there has to be a much nicer way to do this?
Using SQL Server 2008 R2
The solution needs to be entirely T-SQL based though, this occurs in a single stored procedure
So from my understanding of your problem, here's how I would approach it:
My table:
CREATE TABLE [dbo].[deal]
(
[dealName] varchar(100),
[resourceCount] int
)
Then create a unique index on the dealName column:
CREATE UNIQUE NONCLUSTERED INDEX [UQ_DealName] ON [dbo].[deal]
(
[dealName] ASC
)
Once you have the unique index, you can then just handle any exceptions such as a unique constraint violation (error 2601) directly in T-SQL using try/catch
SET NOCOUNT ON;
DECLARE #dealName VARCHAR(100) = 'deal'
DECLARE #resourceCount INT = 8
DECLARE #count INT
BEGIN TRY
BEGIN TRANSACTION
INSERT INTO dbo.deal (dealName,resourceCount)
VALUES (#dealName, #resourceCount)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF ##ERROR = 2601
BEGIN
ROLLBACK TRANSACTION
SET #count = (SELECT COUNT(dealName) FROM dbo.deal WHERE resourceCount = #resourceCount)
SET #resourceCount = (SELECT resourceCount FROM dbo.deal WHERE dealName = #dealName)
SET #dealName = #dealName + ' Cloned ' + CAST(#count AS VARCHAR(100))
BEGIN TRANSACTION
INSERT INTO dbo.deal (dealName,resourceCount)
VALUES (#dealName,#resourceCount)
COMMIT TRANSACTION
END
END CATCH
SELECT * FROM dbo.deal
You can easily put this code into a procedure, all it does is try and insert a deal name with the resource count, if the unique constraint is violated, it enters the catch block, appends the information that you want onto the deal name after finding the resource count of the original deal and then inserts these values.
It's not bulletproof by any means, but I find this technique really useful, not just for enforcing uniqueness, but you can use a similar way of handling exception numbers to deal with deadlocking, primary key violations and loads of other errors, all in T-SQL.
Ensuring the value is unique is easy: Create a unique constraint. If a unique value is inserted MSSQL will throw an exception and you can recover in your application.
Creating a unique name based on a counter (Proj1, Proj2, etc.) is a bit more involved.
Note, this is best mitigated in the web layer, where you can perform an existence check and inform the user prior to attempting the insert that the project name "is already in use." And, if this isnt an option, there are far simpler methods of ensuring uniqueness than enumerating a count as you've described. Appending a datetime or guid would make things relatively easy and would greatly (if not completely) avoid race conditions.
If you absolutely must implement in t-sql as requested then incorporating a counter column somewhere (ie, my "sequence" table below) should help minimize race conditions. I suspect even with the below example you might see some contention under high frequency calls.
--setup
/*
--your existing table
create table dbo.Project
(
[ProjectName] varchar(100) primary key,
[ResourceCount] int
);
--a new table to transactionally constrain the increment
create table dbo.ProjectNameSequence (ProjectName varchar(100) primary key, Seq int);
--cleanup
--drop table dbo.ProjectNameSequence
--drop table dbo.Project
*/
declare #ProjectName varchar(100), #ResourceCount int;
set #ProjectName = 'Test Project XX';
set #ResourceCount = 9;
merge dbo.ProjectNameSequence [d]
using (values(#ProjectName)) [s] (ProjectName) on
d.ProjectName = s.ProjectName
when matched then update set Seq += 1
when not matched then insert values(#ProjectName, 1)
output #ProjectName + case inserted.Seq when 1 then '' else cast(inserted.Seq as varchar) end,
#ResourceCount
into dbo.Project;
select * from dbo.Project
I resolve this using an IF EXISTS inside a WHILE loop..
Personally I can't see what's wrong with this method but will obviously take any comments into account
DECLARE #NameInvalid varchar(100)
DECLARE #DealName varchar(100)
DECLARE #Count int
SET #Count = 1
SET #NameInvalid = 'true'
SELECT #DealName = DealName FROM Deal WHERE DealId = #DealId
--Ensure we get a unique deal name
WHILE( #NameInvalid = 'true')
BEGIN
IF NOT EXISTS(SELECT DealName FROM Deal where DealName = #DealName + ' Cloned ' + cast(#Count as varchar(10)))
BEGIN
INSERT INTO Deal
(DealName)
SELECT #DealName + ' Cloned ' + cast(#Count as varchar(10))
FROM Deal
WHERE DealID = #DealId
SET #NewDealId = ##IDENTITY
SET #NameInvalid = 'false'
END
ELSE
BEGIN
SET #NameInvalid = 'true'
SET #Count = #Count + 1
END
END

Checking sql constraints

I have a question about constraints in SQL, to be exact in transact-sql. I have a database for trips. I created a procedure for adding new trip participant. I am using ms-sql server so foreign key and primary key constraints were added when I created tables. Now in my procedure for adding new participant for a trip I have
insert VoyageThemes(VoyageId,ThemeId) values (#voyageId,#themeId)
now, in VoyageThemes table both VoyageId and ThemeId are primary keys and foreign keys, so when I try to add new values that doesen't correspond to already existing values in database constraint raises it's head.
My question is, can I somehow check if constraint 'said' that I can't add values to table, so I can stop the procedure or I need to manually check in my database if VoyageId and ThemeId exists.
I need to know if those values exists because of this line of code:
update Voyages
set Voyages.Price=Voyages.Price+#costOfTheme*#numOfParticipants
I am updating the price of a trip, so this line of code can only excecute only if there is a corresponding VoyageId and ThemeId
I guess you can use a try/catch?:
...
BEGIN TRY
insert VoyageThemes(VoyageId,ThemeId) values (#voyageId,#themeId)
-- If we are here, then the insert succeeded, proceed with the update
update Voyages
set Voyages.Price=Voyages.Price+#costOfTheme*#numOfParticipants
...
END TRY
BEGIN CATCH
-- insert failed, check error
SELECT #error_number = ERROR_NUMBER(),
#error_severity = ERROR_SEVERITY(),
#error_state = ERROR_STATE()
IF #error_number = 547
-- constraint violation
BEGIN
PRINT '...'
END
ELSE
-- propagate error
BEGIN
RAISERROR(#error_number, #error_severity, #error_state) WITH LOG
END
END CATCH
Rather than INSERT, use MERGE to create a row only if it does not already exists e.g.
MERGE INTO VoyageThemes
USING (
VALUES (#voyageId, #themeId)
) AS S (VoyageId, ThemeId)
ON VoyageThemes.VoyageId = S.VoyageId
AND VoyageThemes.ThemeId = S.ThemeId
WHEN NOT MATCHED THEN
INSERT (VoyageId, ThemeId)
VALUES (VoyageId, ThemeId);

Postgresql: how to create table only if it does not already exist?

In Postgresql, how can I do a condition to create a table only if it does not already exist?
Code example appreciated.
I'm not sure when it was added, but for the sake of completeness I'd like to point out that in version 9.1 (maybe before) IF NOT EXISTS can be used. IF NOT EXISTS will only create the table if it doesn't exist already.
Example:
CREATE TABLE IF NOT EXISTS users.vip
(
id integer
)
This will create a table named vip in the schema users if the table doesn't exist.
Source
create or replace function update_the_db() returns void as
$$
begin
if not exists(select * from information_schema.tables
where
table_catalog = CURRENT_CATALOG and table_schema = CURRENT_SCHEMA
and table_name = 'your_table_name_here') then
create table your_table_name_here
(
the_id int not null,
name text
);
end if;
end;
$$
language 'plpgsql';
select update_the_db();
drop function update_the_db();
Just create the table and don't worry about whether it exists. If it doesn't exist it will be created; if it does exist the table won't be modified. You can always check the return value of your SQL query to see whether the table existed or not when you executed the create statement.
I think to check the pg_class table perhaps help you, something like that:
SELECT COUNT (relname) as a FROM pg_class WHERE relname = 'mytable'
if a = 0 then (CREATE IT)
Regards.
This is an old question. I'm only bringing back to suggest another answer. Note: other better answers already exist, this is just for educational purposes.
The easiest way is to do what others have said; perform the CREATE TABLE if you want to keep the existing data, or perform a DROP IF EXISTS and then a CREATE TABLE, if you want a freshly created table.
Another alternative is to query the system table for its existence and proceed from there.
SELECT true FROM pg_tables WHERE tablename = <table> [AND schemaname = <schema>];
In use:
-- schema independent:
SELECT true FROM pg_tables WHERE tablename = 'foo';
-- schema dependent:
SELECT true FROM pg_tables WHERE tablename = 'foo' AND schemaname = 'bar';
If it matches you'll have a true value, otherwise it should return an empty dataset. You can use that value to determine if you need to perform a CREATE TABLE.
The best answer has been given by Skalli if you're running Postgresql 9.1+.
If like me you need to do that with Postgresql 8.4, you can use a function with a 'duplicate_table' exception catch.
This will ignore the generated error when the table exists and keep generating other errors.
Here is an example working on Postgresql 8.4.10 :
CREATE FUNCTION create_table() RETURNS VOID AS
$$
BEGIN
CREATE TABLE my_table_name(my_column INT);
EXCEPTION WHEN duplicate_table THEN
-- Do nothing
END;
$$
LANGUAGE plpgsql;
What I used to check whether or not a table exists (Java & PostgreSQL)
prior to creating it. I hope this helps someone.
The create table portion is not implemented here, just the check to see if
a table already exists.
Pass in a connection to the database and the tableName and it should return whether
or not the table exists.
public boolean SQLTableExists(Connection connection, String tableName) {
boolean exists = false;
try {
Statement stmt = connection.createStatement();
String sqlText = "SELECT tables.table_name FROM information_schema.tables WHERE table_name = '" + tableName + "'";
ResultSet rs = stmt.executeQuery(sqlText);
if (rs != null) {
while (rs.next()) {
if (rs.getString(1).equalsIgnoreCase(tableName)) {
System.out.println("Table: " + tableName + " already exists!");
exists = true;
} else {
System.out.println("Table: " + tableName + " does not appear to exist.");
exists = false;
}
}
}
} catch (SQLException sqlex) {
sqlex.printStackTrace();
}
return exists;
}
The easiest answer is :
catch{
#create table here
}
This creates a table if not exists and produces an error if exists. And the error is caught.
http://www.postgresql.org/docs/8.2/static/sql-droptable.html
DROP TABLE [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
Try running a query on the table. If it throws an exception then catch the exception and create a new table.
try {
int a = db.queryForInt("SELECT COUNT(*) FROM USERS;");
}
catch (Exception e) {
System.out.print(e.toString());
db.update("CREATE TABLE USERS (" +
"id SERIAL," +
"PRIMARY KEY(id)," +
"name varchar(30) NOT NULL," +
"email varchar(30) NOT NULL," +
"username varchar(30) NOT NULL," +
"password varchar(30) NOT NULL" +
");");
}
return db;