Stored Procedure Select data from Server A and Insert data to Server B - sql

I would like to ask about how to write the Stored Procedure Select data from Server A and Insert data to Server B?

1 . Create a linked server using steps at below link
https://www.sqlshack.com/how-to-create-and-configure-a-linked-server-in-sql-server-management-studio/
Create a synonym for the table from the linked server you are going to use if there is only one table otherwise create synonym for that server so you dont have to use the complete name and if the server changes in future you dont have to go and change in every procedure instead you can just change the synonym.
CREATE SYNONYM MySyn
FOR LinkedServerName.DatabaseName.SchemaName;
GO
Use the synonym in your query to fetch the data.
create procedure procedureName
as
begin
insert into destDB.schema.tablename select * from mysyn.sourcetablename
end

Related

How to use SAS data set brought to SQL Server temporary table and use with another temp table to join,update

Using SAS Enterprise Guide Version 7.1 64 bit.
I cannot create base tables in SQL Server thus can only create temporary table for data processing.
I am also pulling data over from a SAS data set to a global temporary table as(the SAS data set is teradata table pushed to sas-(step2). I need to update holiday table.
I also cannot see how many records are updated in the log (if there is a way to get it, it will be helpful as that way i know the code is working) - I have the sastraceloc but that is not showing update counts in a table.
I finally need to update ##t1 (step4) table created in step 1 with fields from ##holidays table (step2), how do I code this? Am I using the execute, proc sql combination correctly?
Step #1
LIBNAME tmpdta ODBC DATAsrc=datasrcname INSERTBUFF=32767
USER='uid' PASSWORD="pwd" connection=shared;
LIBNAME loc '/c/folder/data';
PROC SQL exec noerrorstop;
CONNECT TO odbc as test(DSN=datasrcname USER='uid' PASSWORD="pwd" connection=shared;
connection=shared);
execute
(create table ##t1
id int,
name varchar(50),
address varchar(100)
)by test;
-- end of 1
step #2
data tmpdt.'##holidays'n;
set loc.holidayexpns;
run;
step #3
proc sql;
connect using tmpdt;
execute
(
update u SET
fee=0,
month=5
FROM tmpdt.##holidays u
)by tmpdt;
step #4
PROC SQL exec noerrorstop;
CONNECT TO odbc as test(DSN=datasrcname USER='uid' PASSWORD="pwd" connection=shared;
connection=shared);
execute
(
update xyz
set a.fee=b.fee,
a.month=b.month
from tmpdt.##holidays h
join ##t1 xyz on
h.id=xyz.id
)by test;
The execute native-query will not know the SAS reference tmpdt., tmpdt will be known to your user login only if on the SQL Server side you have access to a catalog of like name. Did you mean to indicate tempdb ?
Per documentation
Any return code or message that is generated by the DBMS is available in the macro variables SQLXRC and SQLXMSG after the statement completes.

How do I update triggers across multiple databases?

I have a query that I can select the databases from the sys.databases with the triggers that I wish to update. From there I can create a cursor. However when I go into the cursor to update my triggers using a dynamic db name #DatabaseExecuteName that is set to MyDatabaseName.dbo I receive the error ''CREATE/ALTER TRIGGER' does not allow specifying the database name as a prefix to the object name.' Because I am in a cursor I am not able to execute a USE MyDatabaseName ... GO, the GO statement is not allowed inside the CURSOR. I have tried SQLCMD MODE :setvar DatabaseName "MyDatabaseName" with USE [$(DatabaseName)]; to try to set the use database. I feel I am very close however my strength is not SQL queries. I could use some assistance on what I am missing.
You can nest EXEC calls so that you can use a USE and then execute a further statement and you don't need to use GO to seperate the batches. This is a complete script to demonstrate the technique:
create database DB1
go
create database DB2
go
use DB2
go
create table T1 (ID int not null)
go
create table T2 (ID int not null)
go
use DB1
go
exec('use DB2; exec(''create trigger T_T on T1 after insert as
insert into T2(ID) select i.ID from inserted i'')');
select DB_NAME()
insert into DB2..T1(ID) values (1),(2);
select * from DB2..T2
Which then shows that this connection is still in the DB1 database, but the trigger was successfully created on the T1 table within the DB2 database.
What you have to watch for is getting your quote-escaping correct.

How to redirect a request for DB1 to DB2

Suppose I have two databases named DB1 and DB2. In DB1, there is a table named Student, In DB2, there is a stored procedure named SP1. In SP1, I am selecting data of Student Table using below query :
Select *from DB1.dbo.Student.
I have more than 300 stored procedures having above said cross database communication. Now, I want to change my database from DB1 to DB3 that is identical to DB1 from data and schema perspective.
For this, I also have to modify all 300 stored procedures that are having fully-qualified database name. Now, the query will likely to be as follows :
Select *from DB3.dbo.Student
I don't want to change all stored procedure to point DB3 now, also don't want to change my queries written in stored procedure into dynamic SQL (I know this can be done by creating dynamic SQL).
Is it possible if We run DB1.dbo.Student, It will redirect to DB3.dbo.Student. Any intermediate layer or any SQL setting.
It'll be very big help for me. Thanks In Advance !!
If the purpose of your database renaming is to migrate a database, then why not rename the databases themselves?
e.g. say rename DB1 to DB1_old and then rename DB3 to DB1
I would simply script out all stored procedures using SQL Server script generator tool. Then do a find replace on the script and find text ‘DB1.dbo.’ and replace with ‘DB3.dbo.’
In the future you might want to consider using synonyms to reference external tables then you would only have to update the synonyms instead of all of your procedures. Please see following MSDN article on synonyms:
https://msdn.microsoft.com/en-us/library/ms187552.aspx
Example use of synonym:
USE [DB1]
GO
-- Create a synonym for table A located in DB2.
CREATE SYNONYM [dbo].[External_TableA] FOR [DB2].[dbo].[TableA]
GO
-- Synonym is pointing to TableA in DB2 , select statement will return data from DB2 tabla A.
SELECT *
FROM [External_TableA]
GO
-- Point the Synonym to same table but on DB3
DROP SYNONYM [dbo].[External_TableA]
CREATE SYNONYM [dbo].[External_TableA] FOR [DB3].[dbo].[TableA]
GO
-- No update was needed on views or stored procedure.
-- Synonym is pointing to TableA in DB3 , select statement will return data from DB3 tabla A.
SELECT *
FROM [External_TableA]
The follow query will generate the required DROP and CREATE script to remap your synonyms from the old database to the new database.
DECLARE #oldDB NVARCHAR(100) = 'DB2';
DECLARE #newDB NVARCHAR(100) = 'DB3';
SELECT 'DROP SYNONYM [dbo].[' + name + ']' AS [Drop Script]
,'CREATE SYNONYM [dbo].[' + name + '] FOR ' + REPLACE(base_object_name, #oldDB, #newDB) AS CreateScript
FROM sys.synonyms
ORDER BY name
its better to use USE Keyword
use [database name you want to access]
Queries and stored procedure you want to use
GO
eg
use [db1]
select *from yourTableName
exec yourStoredProcedure parm1,parm2,....
Go

Using synonyms in stored procedures

I have a synonym for a table in another DB defined
using
create synonym TableA for otherDb.dbo.TableA
I have a locally defined stored procedure
CREATE PROCEDURE dbo.spGetTableA
AS
BEGIN
SELECT * FROM TableA
END
Now when I call the SP
EXEC spGetTableA
I get the following error
Invalid object name 'TableA'
While calling the SQL directly SELECT * FROM TableA
works perfectly.
Any idea what I'm missing for this to work?
You are probably calling the stored procedure from a user whose default schema is not dbo. Therefore you should always reference the schema both when you create the synonym and when you reference the table in a query.
DROP SYNONYM TableA;
GO
CREATE SYNONYM dbo.TableA FOR OtherDB.dbo.TableA;
GO
ALTER PROCEDURE dbo.spGetTableA
AS
BEGIN
SELECT * FROM dbo.TableA;
END
GO
EXEC dbo.spGetTableA;
I wish I could bold all of those dbo. references within the code. They are important and should ALWAYS be there.
Please read:
Bad habits to kick : avoiding the schema prefix

Why does Microsoft SQL Server check columns but not tables in stored procs?

Microsoft SQL Server seems to check column name validity, but not table name validity when defining stored procedures. If it detects that a referenced table name exists currently, it validates the column names in a statement against the columns in that table. So, for example, this will run OK:
CREATE PROCEDURE [dbo].[MyProcedure]
AS
BEGIN
SELECT
Col1, Col2, Col3
FROM
NonExistentTable
END
GO
... as will this:
CREATE PROCEDURE [dbo].[MyProcedure]
AS
BEGIN
SELECT
ExistentCol1, ExistentCol2, ExistentCol3
FROM
ExistentTable
END
GO
... but this fails, with 'Invalid column name':
CREATE PROCEDURE [dbo].[MyProcedure]
AS
BEGIN
SELECT
NonExistentCol1, NonExistentCol2, NonExistentCol3
FROM
ExistentTable
END
GO
Why does SQL Server check columns, but not tables, for existence? Surely it's inconsistent; it should do both, or neither. It's useful for us to be able to define SPs which may refer to tables AND/OR columns which don't exist in the schema yet, so is there a way to turn off SQL Server's checking of column existence in tables which currently exist?
This is called deferred name resolution.
There is no way of turning it off. You can use dynamic SQL or (a nasty hack!) add a reference to a non existent table so that compilation of that statement is deferred.
CREATE PROCEDURE [dbo].[MyProcedure]
AS
BEGIN
CREATE TABLE #Dummy (c int)
SELECT
NonExistantCol1, NonExistantCol2, NonExistantCol3
FROM
ExistantTable
WHERE NOT EXISTS(SELECT * FROM #Dummy)
DROP TABLE #Dummy
END
GO
This article in MSDN should answer your question.
From the article:
When a stored procedure is executed for the first time, the query
processor reads the text of the stored procedure from the
sys.sql_modules catalog view and checks that the names of the objects
used by the procedure are present. This process is called deferred
name resolution because table objects referenced by the stored
procedure need not exist when the stored procedure is created, but
only when it is executed.