Customized Table Names in Sql Server - sql

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.

Related

If not exist clause SQL statement

so I found this sql query in a project I am succeeding. This is the first time I encountering this clause/statement. I understand that this is to look if the table exist before creating one and that Object_ID is the table name that is to be created.
My questions are:
Does sysobject mean the database?
What is the Object property?
I know that it is not the columns inside the table to be created.
The columns are : dtb_color_id and description.
can someone explain this to me. please?
IF NOT EXISTS(SELECT * FROM SYSOBJECTS WHERE ID = OBJECT_ID('DTB_COLOR') AND OBJECTPROPERTY(ID,'ISUserTable') = 1)
BEGIN
.......some query I understand
END
sysobjects, OBJECTPROPERTY and OBJECT_ID are used in Microsoft SQL Server. They are part of the SQL Server DMVs and system functions/procedures used to query and manipulate the metadata.
sys.sysobjects is simply the list of all objects (tables, views, SPs, functions, etc) on the server in the active database. Please note, that sys.sysobjects is deprecated and is only available for backward compatibility. Use sys.objects instead
https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/system-dynamic-management-views?view=sql-server-ver16
It has (as far as I know) no meaning in MySQL, unless somebody specifically created them.
You can also use INFORMATION_SCHEMA which is available in MySQL too (however slightly different in different RDBMS).
MSSQL INFORMATION_SCHEMA: https://learn.microsoft.com/en-us/sql/relational-databases/system-information-schema-views/system-information-schema-views-transact-sql?view=sql-server-ver16
MySQL INFORMATION_SCHEMA: https://dev.mysql.com/doc/refman/8.0/en/information-schema.html
SQL Server has no CREATE TABLE IF NOT EXISTS construct, a variation of the mentioned condition is commonly used to imitate that.
This is a way in SQL Server to check if a table exists in the active database and to perform actions according to the result, like creating the table.
OBJECTPROPERTY simply checks (in this case) if the table is a user created one.
https://learn.microsoft.com/en-us/sql/t-sql/functions/objectproperty-transact-sql?view=sql-server-ver16
I would remove the OBJECTPROPERTY condition in case the part you understand is a CREATE TABLE statement. You don't want to create a table which has a similar name to any system table/view, also you don't want to execute the CREATE TABLE if there is a VIEW with the same name (table creation will fail)
Yes sysobject means database.
The OBJECTPROPERTY() function returns information about schema-
scoped objects in the current database. Use this to check if an
object is a table, view, stored procedure, etc. You can also use
it to check if a table has a primary key, foreign key, foreign
key reference, etc.
For more details : https://learn.microsoft.com/en-us/sql/t-sql/functions/objectpropertyex-transact-sql?view=sql-server-ver16
In this scenario it is used to check whether it is user table or
not. The result of the ISUserTable property is 1 when it is user
table otherwise returns 0.
Here the following steps are followed:
First, it executes the select statement inside the IF Exists
If the select statement returns a value that condition is TRUE for IF Exists
It starts the code inside a begin statement
DTB_COLOR - May be a stored procedure

create table using exsiting table update/link to column

I want to create a new table with one of the columns linked/updated by a table on another database (but on the same server).
so when table A column is updated it will automatically update table b's column with the same information no data will be entered into this column from table b.
I have tried various different ways but can't find a way to do this with out updating column manually or setting up a server agent any help would be great.
if you want to make cross server query, please check sp_addlinkedserver
https://msdn.microsoft.com/en-us/library/ms190479.aspx
Once it is linked, just create a trigger, where you can use
select * from [server].[database].[schema].[table]

a special case when modifing the database

sometimes i face the following case in my database design,, i wanna to know what is the best practice to handle this case:::
for example i have a specific table and after a while ,, when the database in operation and some real data are already entered.. i need to add some required fields (that supposed not to accept null)..
what is the best practice in this situation..
make the field accept null as (some data already entered in the table ,, and scarify the important constraint )and try to force the user to enter this field through some validation in the code..
truncate all the entered data and reentered them again (tedious work)..
any other suggestions about this issue...
It depends on requirements. If the data to populate existing rows for the new column isn't available immediately then I would generally prefer to create a new table and just populate new rows when the data exists. If and when you have all the data for every row then put the new column into the original table.
If possible i would set a default value for the new column.
e.g. For Varchar
alter table table_name
add column_name varchar(10) not null
constraint column_name_default default ('Test')
After you have updated you could then drop the default
alter table table_name
drop constraint column_name_default
A lot will come down to your requirements.
It depends on your application, your database scheme, your entities.
The best way to go about it is to truncate the data and re - enter it again, but it need not be too tedious an item. Temporary tables and table variables could assist a great deal with this issue. A simple procedure comes to mind to go about it:
In SQL Server Management Studio, Right - click on the table you wish to modify and select Script Table As > CREATE To > New Query Editor Window.
Add a # in front of the table name in the CREATE statement.
Move all records into the temporary table, using something to the effect of:
INSERT INTO #temp SELECT * FROM original
Then run the script to keep all your records into the temporary table.
Truncate your original table, and make any changes necessary.
Right - click on the table and select Script Table As > INSERT To > Clipboard, paste it into your query editor window and modify it to read records from the temporary table, using INSERT .. SELECT.
That's it. Admittedly not quite straightforward, but a well - kept database is almost always worth a slight hassle.

How do I create a table alias in MySQL

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.

Are writing triggers in MS SQL server the same as writing them in MS Access?

I have written the following trigger in SQL server:
create trigger test_trigger
on invoice -- This is the invoice table
for insert
as
declare #invoiceAmount int -- This is the amount specified in the invoice
declare #custNumber int -- This is the customer's id
--use the 'inserted' keyword to access the values inserted into the invoice table
select #invoiceAmount = Inv_Amt from inserted
select #custNumber = cust_num from inserted
update customer
set amount = #invoiceAmount
where Id = #custNumber
Will this be able to run in MS Access or is the syntax different?
The Access database engine (formerly called Jet) does not have triggers and regardless has no control-of-flow syntax e.g. a PROCEDURE must consist of exactly one SQL statement.
Tell us what you really want to do and there could be an alternative syntax.
For example, you could create a new key using a UNIQUE constraint on invoice, (cust_num, Inv_Amt), a FOREIGN KEY customer (id, amount) to reference the new key, a VIEW that joins the two tables on the FOREIGN KEY columns and exposing all four columns, then INSERT into the VIEW rather than the table 'invoice'; you may want to use privileges to prevent INSERTs to the base table but user level security was removed from the new Access 2007 engine (called ACE).
But, if you don’t mind me saying, I think your trigger doesn't reflect a real life scenario. A column vaguely named 'amount' in table 'customer' to hold the most recent invoice amount? What about when the inserted logical table contains rows for more than one customer? As I say, I think you need to tell us what you are really trying to achieve.
Access doesn't have triggers
Your trigger that you show here will bomb out since it does not take into account multirow updates the moment someone updates more than one row (and don't say it won't happen because it will better to practice some defensive coding)
Triggers fire per batch not per row, please read Multirow Considerations for DML Triggers
join inserted pseudo table and the invoice table instead to update the values...that works for 1 and more than 1 row
They may be coming in Access 2010? http://blogs.msdn.com/access/archive/2009/08/13/access-2010-data-macros-similar-to-triggers.aspx
MS Access doesn't have triggers.
That is, the the Access Jet engine (which creates .mdb files). If Access is connecting to a database server, then it will use whatever triggers are in that database.
I've never come across triggers in Access unless it's dealing with ADP on SQL Server. So your answer is yes, it's the same if you're on SQL Server for the backend, and no if the table is stored in Access.