I am using Power Designer to create a database model. In one of my tables, I have created a Check constraint that calls a function to validate the attribute. The script for my table creation looks like this
create table tbl_Inventory (
Id int identity,
Name VARCHAR(50) not null
constraint CK_Inventory_Name check (([dbo].[fn_CheckNameComplexLogic]([Name]) = 1)),
constraint PK_Inventory primary key (Id),
)
I have also created a function fn_CheckNameComplexLogic that performs the check.
When I try to use the code generation tool by going Database->Generate Database. The generated code always place create table before create function. Because my table depends on the function, the scripts always errors out. I could manually edit the generated code, but I am wondering if there is a place in PowerDesigner for configuring this.
Thanks for your help.
If may be a little overkill, but you can change the Generation Order to put (all) the functions (included in the Procedure category) before the Table.
embed the DBMS in your model with Database>Change Current DBMS
edit it with Database>Edit Current DBMS
change the order in the Script\Objects\GenerationOrder item (using the XML view)
put Procedure above Table
Simply add condition into Additional Checks of column properties tab after all constructs like %MINMAX% and %LISTVAL% and %CASE% and %RULES% and write here your condition ...
Related
I have 3 tables, "Courses"(id, start_date), "Subscriptions"(id, assistant_id, course_id, date) and "Assistants"(id, registration_date).
Subscriptions reference Courses and Assistants with foreign keys as you see.
I need to add CHECK constraint that will prevent to create Subscription record if referenced Courses.start_date is older than referenced Assistants.registration_date. Is there a way to do this in Libre Base?
Table organization could not be changed.
Such a CHECK constraint cannot be created with the default engine. From the HSQLDB 1.8 documentation:
ALTER TABLE <tablename> ADD [CONSTRAINT <constraintname>]
CHECK (<search condition>);
Adds a check constraint to the table. In the current version, a check constraint can reference only the row
being inserted or updated.
This means that commands like the following from TestSelfCheckConstraints.txt produce an error:
/*e*/CREATE TABLE TC6(A CHAR, B CHAR, C CHAR, D INT, CHECK(A IN (SELECT A FROM
TC5)));
So, to perform such a check, you will have to verify it ahead of time (or afterwards) using a query. This could be done for a form by adding a macro in the Events tab. See this post for ideas: https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=21414.
The default engine is rather old, so for such complex requirements it may be better to set up LibreOffice Base to use a different database engine. For example using MySQL, it is possible to set up a stored procedure trigger to do this kind of checking. See CHECK constraint in MySQL is not working.
I have a table called Table 1. I'm trying to create an after-insert trigger for a Table 1; whereby, whenever a user enters a record, the trigger will create a new table named after the record that triggered its creation.
Please help, I'm using SQL Server 2008
This sounds super non-relational-database-design-ish. I would heavily advise against this in almost every case. And I say "almost" only to allow for artistic freedom of development, I can't think of a single case where this would be appropriate.
That said, if you do in fact want this, you can use dynamic SQL to create a table.
You can build the SQL in your trigger, but basically you want something like:
EXEC 'CREATE TABLE ' + #tableName + ' (ID INT IDENTITY(1,1))';
Of course, the columns are up to you, but that should get you started.
But while we're at it, what you should (probably) be doing is using a single table with a one-to-many relationship to the table on which your trigger is currently assigned.
For instance, if you have a table Users with a column for email and you're looking to create a table for each user's favorites on your website, you should instead consider adding an identity column for user IDs, then reference that in a single UserFavorites table that has UserId and PostId columns, and the appropriate foreign keys implemented.
When I create table that has definition of FK's directly in CREATE command and target table does not exists yet, results in error.
Can checking, if target table exists, be somehow suspended?
my DBMS is Postgres.
Example (pseudocode):
create table "Bar"
foo_id integer FK of "Foo"."id",
someattr text;
create table "Foo"
id integer;
Example is in wrong order, thats why it wont run.
I'm trying to recreate databse in batch, based on definitions in many sql files.
When I create table that has definition of FK's directly in CREATE command and target table does not exists yet, results in error.
Can checking, if target table exists, be somehow suspended?
The best ways to deal with this are likely:
Create your tables in the correct order, or
Create the constraints
outside the table creation, after all tables are created.
Brute force is always an option.
Keep on running your DDL scripts in until you get a run with no errors.
More elegance requires a sequential structuring of your scripts.
Adding existence checks is possible, but I am not too familiar with the postgres metadata.
I wanted to modify a column in a sql server 2005 table to IDENTITY(1,1)
Incidentally this table is empty and the column to be changed is a primary key.
This column is also a foreign key for two other tables.
After googling I found that you cannot use Alter table syntax to modify a column and make it an indentity column.
Link #1 : How do I add the identity property to an existing column in SQL Server
Link #2 : Adding an identity to an existing column -SQL Server
I ended up checking the dependent tables (2 of them) removing the foreign keys (generated the script from SSMS) then dropping the main table then re-creating with identity. (could try the rename option here as well)
Then re-created the foreign keys for the earlier dependent two tables.
But all this was manual work, any scripts or SPs out there to make this easier.
Ideally all these steps would be done by such a script/tool/utility:
Check dependent tables keys
Generate Create and drop foreign key scripts for this
Generate create script for the main table
drop the main table (or rename the table if the table has data)
re-create the table with identity column enabled
re-create foreign keys
You can use SSMS to generate a script (Edit a table, save script), but otherwise it's a manual process as you identified.
The SSMS scripts will pick up dependencies etc. For this kind of work, I tend to use SSMS to generate a basic script, pimp it a bit, run it carefully, then use a comparison tool (such as Red Gate compare) to generate a safer version.
Edit: The SSMS error is not an error, it's a safety check that can be switched off
(This is merely a follow-up to gbn's post with more details -- it isn't all that easy to figure this stuff out.)(
It isn't impossible to write a utility to do this, just very complex and very hard. Fortunately, Microsoft has already done it -- its called SSMS (or SMO?). To generate such a script:
In the Object Explorer, drill down to the database and table that you want to modify
Right click and select Design
Make the desired changes to the one table in the design screen. It's reasonably intuitive.
To add/remove the identity property, select the column in the upper pane, and in the lower pane/"Column Properties" tab, expand and configure the settings under "Identity Specification".
To generate a script to implement all your changes, incorporating all the dependent key changes, click on the "Generate Change Script" toolbar button. This is also an option under the "Table Designer" menu.
I also do this to generate scripts (that I later modify--SSMS doesn't always produce the most efficient code.) Once done, you can exit out without saving your changes -- leaving you a DB you can test your new script on.
drop the pk and build the same datatype column
copy the data of the column which you want to set identity to the new column.
drop the old column
reset primary key
ALTER TABLE UserRole
DROP CONSTRAINT PK_XX
ALTER TABLE XX
ADD newX int not null identity(1,1) primary key
update XX set newX = oldX
alter table XX
DROP COLUMN oldX
this is the simplest way to set identity column.
if you don't want to use the long generated script.
I am migrating an MS Access application (which has linked tables to a MSSQL Server) to MySQL.
As a means to overcome some MSAccess table naming problems, I am seeking a solution to add a MySQL table alias that will point to an existing table in the MySQL database. Ideally I would like to create the alias 'dbo_customers' in mysql that would point to the customers table also in mysql.
To be clear I am not wanting to alias a table name inside a query like this:
SELECT * FROM customers AS dbo_customers
But rather I would like to be able issue the following query:
SELECT * FROM dbo_customers
and have it return data from the customers table.
Off the top of my head
CREATE VIEW dbo_customers AS
SELECT * FROM customers
Maybe not the best solution but should work as the view is updatable. Will definitely work for Read Only
You can create a View.
CREATE VIEW dbo_customers AS SELECT * FROM customers;
If that doesn't work for you, you could try creating a shadow-copy of the table, and use Triggers to keep the tables synced.
For example:
CREATE TABLE t1( id serial primary key, field varchar(255) not null );
CREATE TABLE dbo_t1( id serial primary key, field varchar(255) not null );
-- INSERT trigger
CREATE TRIGGER t1_dbo_insert AFTER INSERT ON t1
FOR EACH ROW BEGIN
INSERT INTO dbo_t1 SET field = NEW.field;
-- No need to specify the ID, it should stay in-sync
END
-- UPDATE trigger
CREATE TRIGGER t1_dbo_update AFTER UPDATE ON t1
FOR EACH ROW BEGIN
UPDATE dbo_t1 SET field = NEW.field WHERE id = NEW.id;
END
-- DELETE trigger
CREATE TRIGGER t1_dbo_delete AFTER DELETE ON t1
FOR EACH ROW BEGIN
DELETE FROM dbo_t1 WHERE id = OLD.id;
END
Not exactly an 'alias', and far from perfect. But it is an option if all else fails.
there is a simpler solution for MySQL via MERGE table engine:
imagine we have table named rus_vacancies and need its English equivalent
create table eng_vacancies select * from rus_vacancies;
delete from eng_vacancies;
alter table eng_vacancies ENGINE=MERGE;
alter table eng_vacancies UNION=(rus_vacancies);
now table rus_vacancies equals to table eng_vacancies for any read-write operations
one limitation - original table must have ENGINE=MyISAM (it can be easily done by "alter table rus_vacancies ENGINE=MyISAM")
You could create a view named dbo_customers which is backed by the customers table.
#OMG Ponies ponies said in a comment:
Why not rename the table?
...and it seems the obvious answer to me.
If you create an ODBC linked table for the MySQL table customers it will be called customers and then all you have to do is rename the table to dbo_customers. There is absolutely no need that I can see to create a view in MySQL for this purpose.
That said, I'd hate to have an Access app that was using SQL Server table names when the MySQL tables were not named the same thing -- that's just confusing and will lead to maintenance problems (i.e., it's simpler for the linked tables in the Access front end to have the same names as the MySQL tables, wherever possible). If I were in your position, I'd get a search and replace utility and replace all the SQL Server table names with the MySQL table names throughout the entire Access front end. You'd likely have to do it one table at a time, but in my opinion, the time it takes to do this now is going to be more than made up for in clarity going forward with development of the Access front end.
I always rename my "linked to SQL" tables in Access from
{dbo_NAME} to {NAME}.
The link creates the table name as {dbo_NAME} but access occasionally has problems with the dbo_ prefix.
Aliases would be nice, yet MySQL does NOT have such a feature.
One option that may serve your needs, besides creating a view, is to use the FEDERATED storage engine locally.
CREATE TABLE dbo_customers (
id INT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL DEFAULT '',
PRIMARY KEY (id),
)
ENGINE=FEDERATED
DEFAULT CHARSET=latin1
CONNECTION='mysql://fed_user#localhost:9306/federated/customers';
There are currently some limitations with the FEDERATED storage engine. Here are a couple especially important ones:
FEDERATED tables do not support transactions
FEDERATED tables do not work with the query cache
I'd like to mention a bad solution I explored (and abandoned), which was to use hardlinks on the .frm, .MYD and .MYI files corresponding to my table in /var/lib/mysql/{name_of_my_database}/.
It does, however, NOT work. For InnoDB tables, it simply cannot (even if you hardlink the .idb file) because tables are also referenced in ibdata1.
For MyISAM tables, it kind of works, except it doesn't because in memory, the tables are still distinct and thus do not share cache. So if you write a row to original_table, it won't immediately appear in aliased_table. You would have to flush tables first… which defeats the purpose and even causes data loss (if you insert a row in both the original and the alias before flushing, only one row is kept).
I thought my experiment was worth mentioning as a cautionary tale.