What is the use of SYNONYM? - sql-server-2008

What is the use of SYNONYM in SQL Server 2008?

In some enterprise systems, you may have to deal with remote objects over which you have no control. For example, a database that is maintained by another department or team.
Synonyms can help you decouple the name and location of the underlying object from your SQL code. That way you can code against a synonym table even if the table you want is moved to a new server/database or renamed.
For example, I could write a query like this:
insert into MyTable
(...)
select ...
from remoteServer.remoteDatabase.dbo.Employee
but then if the server, or database, schema, or table changes it would impact my code. Instead I can create a synonym for the remote server and use the synonym instead:
insert into MyTable
(...)
select ...
from EmployeeSynonym
If the underlying object changes location or name, I only need to update my synonym to point to the new object.
http://www.mssqltips.com/sqlservertip/1820/use-synonyms-to-abstract-the-location-of-sql-server-database-objects/

Synonyms provide a great layer of abstraction, allowing us to use friendly and/or local names for verbosely named or remote tables, views, procedures and functions.
For Example
Consider you have the server1 and dbschema as ABC and table name as Employee and now you need to access the Employee table in your Server2 to perform a query operation.
So you have to use like Server1.ABC.Employee it exposes everything ServerName,SchemaName and TableName.
Instead of this you can create a synonym link Create Synonym EmpTable for Server1.ABC.Employee
So you can access like Select * from Peoples p1 inner join EmpTable emp where emp.Id=p1.ID
So it gives the advantages of Abstraction, Ease of change,scalability.
Later on if you want to change Servername or Schema or tablename, just you have to change the synonym alone and there is no need for you do search all and replace them.
If you used it than you will feel the real advantage of synonym. It can also combine with linked server and provide more advantages for developers.

An example of the usefulness of this
might be if you had a stored procedure
on a Users database that needed to
access a Clients table on another
production server. Assuming you
created the stored procedure in the
database Users, you might want to set
up a synonym such as the following:
USE Users; GO CREATE SYNONYM Clients
FOR Offsite01.Production.dbo.Clients;
GO
Now when writing the stored procedure
instead of having to write out that
entire alias every time you accessed
the table you can just use the alias
Clients. Furthermore, if you ever
change the location or the name of the
production database location all you
need to do is modify one synonym
instead of having to modify all of the
stored procedures which reference the
old server.
From: http://blog.sqlauthority.com/2008/01/07/sql-server-2005-introduction-and-explanation-to-synonym-helpful-t-sql-feature-for-developer/

Seems (from here) to create an alias for another table, so that you can refer to it easily. Like as
select * from table longname as ln
but permanent and pervasive.
Edit: works for user-defined functions, local and remote objects, not only tables.

I've been a long-time Oracle developer and making the jump to SQL Server.
But, another great use for synonyms is during the development cycle. If you have multiple developers modifying the same schema, you can use a synonym to point to your own schema rather than modifying the "production" table directly. That allows you to do your thing and other developers will not be impacted while you are making modifications and debugging.
I am glad to see these in SQL Server 2008...

A synonym is a database object that serves the following purposes:
Provides an alternative name for another database object, referred to as the base object, that can exist on a local or remote server.
Provides a layer of abstraction that protects a client application from changes made to the name or location of the base object.
Have never required the first one but the second issue is rather helpful.
msdn is your friend

You can actually create a synonym in an empty database and refer it to an object in another database, and thus make it work as it should even though it is in a completely empty database (besides the synonym that you created of course).

Related

Concept of schema in MySQL

Is there a suggested way to use "schemas" in mysql? For example, if I have one database called events and then I want to have two environments dev and prod, what might be a way to do that? Currently I add a table prefix, but it seems a a bit hack-ish:
you create a separate database for that, because MySQL does not have the concept of schema like e.g. PostgreSQL does.
You create one database for production e.g. prod_database with the table names event and event_type. and one database for dev e.g. dev_database, with the same table names event and event_type. As you always want to have the same table names in different environments.
You could (and should) even use the same database name, if you host the database on different servers. Which for production and development/staging would also make sense e.g. to test server version updates on one setup without affecting production.

How to scope a MySQL JOOQ rename table query to the same database?

I have a scala application that manages multiple MySQL database schemas, which includes modifying (adding, renaming, etc.) tables. The commands are issued over a connection pool that connects to a generic management database in the database server.
Because the application is designed to be cross-database, I use JOOQ to render SQL queries (execution is done via a separate JDBC module).
I experience issues with JOOQs alterTable(...).renameTo(...) DSL - consider the following example:
We have a table "TestTable" in database "TestDatabase". Let's say I want to rename that table simply to "Foo", keeping it in "TestDatabase".
This code:
...
val context = DSL.using(SQLDialect.MYSQL_5_7)
val query = context
.alterTable(table(name("TestDatabase", "TestDatabase")))
.renameTo(name("TestDatabase", "Foo"))
...
Generates: ALTER TABLE `TestDatabase`.`TestTable` RENAME TO `Foo`
However, since the connection pool I'm using is connected to my management database, it just renames the table to "Foo" and moves it to my management database. I would have expected the SQL to be: ALTER TABLE `TestDatabase`.`TestTable` RENAME TO `TestDatabase`.`Foo`. I tried a variety of alternatives to invoke the .renameTo method and convice it to use the fully qualified name, to no avail:
.renameTo(table(name(...) -> same behaviour.
.renameTo("`TestDatabase`.`Foo`") -> Escapes the name with backticks, treats it as one name instead of a qualified name.
I'm wondering if I'm missing something, if this is intended behaviour, or maybe even a bug or design shortcoming of JOOQ.
Is there a way to rename the table using fully qualified names?
Thank you!
That's a bug in jOOQ: https://github.com/jOOQ/jOOQ/issues/8042
Your workaround is close. This doesn't work:
.renameTo("`TestDatabase`.`Foo`")
As you've noticed, behind the scenes, the DSL.name() API is used to wrap the target name, because the renameTo() method doesn't implement the plain SQL templating API. You can, however, explicitly use plain SQL templating by writing as a workaround:
.renameTo(table("`TestDatabase`.`Foo`"))

Coldfusion server mapping to sql server

I have a ColdFusion server connected to MySQL database. Now I am changing the database to an existing MSSql server .. MSSql server has a similar database that of MySQL but the table names and column names are different. My question is that how can I map the new MSSql server to the ColdFusion server without changing the ColdFusion code.. Means without changing the table name and column names in ColdFusion code..
Thanks in advance
If the schemas are different (different column names and number of columns) then you probably have no choice but to refactor your CF code to reflect the new MSSQL schema. If there is a one to one relationship between the table and column names from one DB to the next you could use views - but it would make for a very confusing development environment. Again... each table would have to "match" for number of columns and types of data. Example
Old table "users"
firstname, lastname address
New table "tblUsers"
fname, lname, addr
Given the schemas above, you might have a query in your CF Code that looked like:
<cfquery name="getUsers" datasource="blah">
SELECT firstname, lastname, address
</cfquery>
So it would fail when you switched the DB. However, if you created a view like so:
CREATE VIEW [dbo].[Users]
AS
SELECT u.fname AS firstname,
u.lname AS lastname
u.addr AS address
FROM dbo.tblusers
Then your code would work. Again I am NOT recommending this. Your best course of action is to alter the schema to reflect your code or to refactor your code to work against the new schema. But technically it does answer your question :)
Unless you're already using ORM, here is no handy function or mapping mechanism in CF that would allow you to do this. There may be some manipulation at the driver level, or dipping into the java code that creates the sql strings to do text parsing there, but that's outside of my realm of expertise.
My guess, though, is that you have a lot of queries scattered throughout the application and are therefore daunted at the task of redoing all of them. Personally, I would refactor at least the data access of this app into one or more .cfc's. Even if all you do is wrap each query into a function call and replace the cfquery code with a function call, you're consolidating all of the database calls into one place and can change things much easier going forward.

What is the best way to filter a multi-tenant MySQL database?

In MySQL I have a single database with one schema. In Microsoft Sql Server it is recommended to use a "Tenant View Filter" so in Microsoft Sql Server this gives me exactly what I need.
CREATE VIEW TenantEmployees AS
SELECT * FROM Employees WHERE TenantID = SUSER_SID()
What is the best way to accomplish the same in MySQL? An equivalent to the "Tenant View Filter" will work if it is performs well.
Thanks!!
The query you suggest (that I could find in MSDN) has text afterwards that explains exactly what are its assumptions. In particular, it mentions that it assumes that the "owner" of a row in the Employees table is specified in the TenantID field that is populated according to the SID of the user(s) you are partitioning for.
What that means is that you can replicate the same idea whatever way you decide to implement your data as long as you have clearly defined partitions of the data and know exactly how to associate it with the table you are creating a view for.
In particular, if you configure your system so that each partition accesses the DB with its own credentials, you could use the CURRENT_USER or USER constructs of MySQL as the IDs defining your partitions and the query to create the view would be basically the same as the one suggested in MSDN replacing SUSER_ID with CURRENT_USER.
But if you use the same user to access from all the partitions, then the suggested method is irrelevant on either database server.
Since you need to use your tenantId value to perform filtering, a table valued user defined function would be ideal, as a view normally does not accept parameters. Unfortunately, unlike many other database products MySQL doesn't support table-valued functions. However, there are MySQL hacks that claim to emulate parametrized views. These could be useful for you.
It's a little tricky in MySQL, but it can be done:
CREATE OR REPLACE VIEW {viewName}
AS
SELECT {fieldListWithoutTenantID}
FROM {tableName}
WHERE (id_tenant = SUBSTRING_INDEX(USER( ),'#',1))
I wrote up a full blog post on how I converted a single-tenant MySQL application to multi-tenant in one weekend with minimal changes. https://opensource.io/it/mysql-multi-tenant/

How to accomplish "MySQL cross database reference" with PostgreSQL

We will migrate the database from mysql to postgresql in our product(through java). So we need to change the mysql query to postgresql query in java application. How to create the table i.e., databasename.tablename in postgresql.
For mysql, we can directly create the table e.g create table information.employee.
Here database name is "information" and table name is "employee" . Is it possible to achieve same query in postgresql.
I searched google it says cross database reference is not possible. Please help me.
I saw pg_class table it contains the table names in the specific database, like wise databse and tables relationships are stored in any other table.
This is normally done using schemas rather than databases, which is more or less like how MySQL organizes it anyway.
Instead of
create database xyz
use
create schema xyz
When you create tables, create them:
create table xyz.myTable
you will need to update your search path to see them on the psql command line tool, or if you want to query them without using the schema explicitly. The default schema is public, so when you create a table without a schema name, it ends up in public. If you modify your search_path as below, the default schema becomes the first in the list: xyz.
set search_path=xyz,public,pg_catalog;
and you must not have spaces in that statement. You can do it globally for a user/role too:
alter role webuser set search_path=xyz,public,pg_catalog;
Also, don't forget that postgresql string matches are case sensitive by default (this one catches people out a lot).
If you want to have different physical locations for the files for each schema, you can do that with tablespaces. If you have a look at the postgresql documentation page, they have info on how to do it, it's pretty easy.
database in MySQL == schema in PostgreSQL. So you will most probably want to migrate all your mysql dbs into one postgres db. Then you will be able to do "cross-database" queries.
See my answer to this question: Relationship between catalog, schema, user, and database instance