Cannot find 'server\db' in sys.servers - sql

My SQL Server job is supposed to create a linked server and query it. However there seems to be an issue with the name and I can not figure out where. I tried googling and it seems that linked server is made, but the query "misreads" the name. Please tell why this happens or where am I messing up.
DECLARE #tmp_key VARCHAR(14)
DECLARE #db cursor
DECLARE #sql NVARCHAR(MAX)
exec sys.sp_addlinkedserver '[server\db]'
SET #db = CURSOR FOR
Here is the error part:
SELECT RIGHT('000'+CAST([CONro]AS VARCHAR(4)),4)
FROM [server\db].[TKYHT].[dbo].COMPANY
WHERE [CONro] NOT IN ('1','95','104','105','183','213','275','603','620','802','998','1001','1002',
'1105','1112','1113','1122','1179','1183','1189','1458','1508','1516','1575','1599','1602',
'1691','1841','2184','3073','3074','3980','3989','6158','6164','9990','9999')
ORDER BY [CONro] ASC
The error is;
Cannot find 'server\db' in sys.servers , Verify that the correct
server name was specified. If necessary, execute the stored procedure
sp_addlinkedserver to add the server to sys.servers. [SQLSTATE 42000]
(Error 7202). The step failed.
Some ok code here:
exec sys.sp_dropserver '[server\db]'

Related

Bypassing character limit on OPENQUERY failing use EXECUTE

I am currently using SQL Server Management Studio 17 to connect to an Oracle database instance and then extract some data and insert it into a SQL Server Table I have.
I have tried doing the following:
DROP TABLE IF EXISTS [jerry].[dbo].[purchases]
SELECT * INTO [jerry].[dbo].[purchases] FROM OPENQUERY(OLAP, '
proprietary sql code
');
However the SQL code is about 9500 characters and thus OPENQUERY fails, which is supported by MSDN articles
I referenced these sites:
- MSDN One - MSDN Two
and learned that I can use EXEC to accomplish my goal.
I have tried to implement the following:
EXEC master.dbo.sp_serveroption #server=N'OLAP', #optname=N'rpc out', #optvalue=N'true'
DECLARE #sqlcode VARCHAR(MAX)
SET #sqlcode = 'sql code'
DROP TABLE IF EXISTS [jerry].[dbo].[purchases]
EXEC #sqlcode AT OLAP
However, I am still getting an Invalid Syntax near OLAP error.
I have confirmed that OLAP is the correct name from our DBA and other OPENQUERY functions work just fine (with much shorter SQL statements).
I cannot edit the SQL query
I cannot edit the external OLAP's databases permissions (I am not the DBA nor am I in the security group)
Any assistance is greatly appreciated.
EXEC without parentheses runs a stored procedure.
So try:
truncate table [jerry].[dbo].[purchases]
insert into [jerry].[dbo].[purchases]
exec ( #sqlcode ) at olap
See execute

How to use 'use' command across all database to execute certain script in sql

I have a certain script which I need to execute across all databases in SQL Server. I have used the following logic to loop through all database excluding the system databases.
declare #DBName varchar(500)
DECLARE #Database_id int
DECLARE #Query varchar(MAX)
select #Database_id = MIN(database_id) from sys.databases where database_id>4
while #Database_id is not null
begin
select #DBName=name from sys.databases where database_id=#Database_id
set #Query = 'Use'+#DBName
--some script
Print ''+#DBName+''
exec (#Query)
select #Database_id = MIN(database_id) from sys.databases where database_id>4 AND database_id>#Database_id
end
But the problem is I can't use the 'Use' command with a variable. Is there any other way to make use of 'Use' command to hit the database?
And I don't want to use sp_MSforeachdb command as my query is too long.
Any help would be appreciated!
There is an undocumented function doing this. You can use the question mark in the place of the db's name:
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; EXEC sp_spaceused'
Find this example and more explanations here: http://weblogs.sqlteam.com/joew/archive/2008/08/27/60700.aspx
EDIT: From your comments above I find, that you do not want to includ the system dbs into your run. It seems to be q bit tricky to detect, whether a db is a system db or not but you could go like this:
DECLARE #cmd VARCHAR(1000)='USE [?];IF DB_ID(DB_NAME())<=4 RETURN;EXEC sp_spaceused;'
EXECUTE master.sys.sp_MSforeachdb #cmd;
GO
Read about the flaws here (about SQL Server 2005!): SQL Server: How to tell if a database is a system database?
If you don't like this <=4 you could simply do it like
IF DB_NAME() IN('master','model',... any more names here ... ) RETURN;
The only real restriction I know of is, that sp_MSforeachdb does not like "GO".

SQL Server Linked Server Join

I have added a linked server in my sql server 2008. I want to fetch data from a table and a table valued function residing on my linked server and join this data on a local table by following below given naming convention.
<server>.<database>.<schema>.<table>
However my first problem is I need to fetch <server> part from a table. So when I try to do something like following it fails
Select * FROM #ServerNameVariable.database.dbo.myTable
Any idea how can I form fully qualified linked server table name with a user defined variable ?
My SP is as follows
CREATE PROCEDURE TEST_SP
AS
BEGIN
DECLARE #NetworkDBName VARCHAR(255)
SET #NetworkDBName = '[MyLinkedServerName]'
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
select * from #NetworkDBName + '.' + testDatabase.dbo.Invoice_tb
END
GO
You cannot use variables in place of database, schema or table names.
Instead you can build and execute dynamic SQL statements, using sp_ExecuteSQL.
This example won't work, as the server name is seen as a string and not a server object.
Failed Example
/* Anti-pattern.
* Does not work.
*/
DECLARE #Server SYSNAME = 'Server001';
SELECT
*
FROM
#Server.Database1.dbo.Table1
;
This example shows a method that does work. Here the SQL statement is built as a string, which is then executed.
/* Dynamic SQL statement.
* Will work.
*/
DECLARE #Server SYSNAME = 'Server001';
DECLARE #Statement NVARCHAR(255);
SET #Statement = 'SELECT * FROM ' + QUOTENAME(#Server) + '.Database1.dbo.Table1;';
EXECUTE sp_ExecuteSQL #Statement;
As ever; please be careful when generating and executing dynamic SQL statements. You do not want to open yourself up to SQL injection attacks. Look into OPENROWSET or check the passed server name against the code kindly supplied by #Devart above (SELECT name FROM sys.servers WHERE server_id > 0) before executing.
EDIT 1: Added more detail to the paragraph on SQL injection.
EDIT 2: Removed square brackets from 2nd example query, replaced with QUOTENAME, as per #TTs comment.
Use the name of link server it will a 4 part qualifier e.g
Select * From [Link Server Name ].[Database].[Schema].[Table]

SQL Server dynamic query -- cannot locate linked server

declare #node int = 9044;
DECLARE #sqlCommand NVARCHAR(MAX) =
(
'SELECT * FROM [#node].[database_name].dbo.table_name'
);
DECLARE #paramList NVARCHAR(400) =
(
'#node int'
)
exec sp_executesql #sqlCommand, #paramlist, #node;
So this is the simple query I'm attempting to run. 9044 is fine. Running that query normally works perfectly (obviously I've removed the db and table names). Not entirely sure what is wrong with it. The error I get is:
Msg 7202, Level 11, State 2, Line 1
Could not find server '#node' in sys.servers. Verify that the correct server name was specified. If necessary, execute the stored procedure sp_addlinkedserver to add the server to sys.servers.
Any ideas on how to fix this issue or should I just write the query and use EXEC (#sql)
As per my thinking and test it only allow parameter in query part like in where and other condition.
Try this way.
declare #node int = 9044;
DECLARE #sqlCommand NVARCHAR(MAX) =
(
'SELECT * FROM [#node].[database_name].dbo.table_name'
);
DECLARE #paramList NVARCHAR(400) =
(
'#node int'
)
SET #sqlCommand = REPLACE(#sqlCommand , '#node',#node)
exec sp_executesql #sqlCommand, #paramlist, #node;
You are using 3-dot notation which defines the server.db.table #nodes is looking for a server of this name ...are you looking for this server name dynamically.. the best way would be to create a linked server object or alias and refer to it this was i.e
MyServer = dev-sql-server.AdventureWorks etc
Or you may just need to get rid of the extra [#node].

Execute stored proc with OPENQUERY

I have SQL Server 2008 with a linked Sybase server and I am trying to execute a stored procedure on the Sybase server using OPENQUERY. If I have a stored proc that doesn't take parameters it succeeds fine. If I have a stored proc with parameters it fails. I even tried a very basic stored proc that only took an int an that still failed. Below is the syntax I am using:
select * from
OPENQUERY([LINKSERVER],'exec database.user.my_stored_proc ''AT'',''XXXX%'',''1111'',1')
Msg 7357, Level 16, State 2, Line 3
Cannot process the object "exec database.user.my_stored_proc 'AT','XXXX%','1111',1". The OLE DB provider "ASEOLEDB" for linked server "LINKSERVER" indicates that either the object has no columns or the current user does not have permissions on that object.
As the proc will execute just fine without parameters, I don't think it is a permission issue.
This worked for me,
SELECT * FROM OPENQUERY(LOCALSERVER, 'SET FMTONLY OFF EXEC snr.dbo.GetAllSignals #controlRunId = 25, #experimentRunId = 26')
I was creating temporary tables, and that's why i got access denied
Here is more info http://www.sommarskog.se/share_data.html#OPENQUERY
I create a sp that doesn't return any value and it doesn't work.
Your SP in mysql have to return a value!
for example I do this in "mysql":
CREATE DEFINER=`root`#`localhost` PROCEDURE `MyPro`(IN `Name` VARCHAR(50), IN `Id` INT, OUT `Result` INT)
MODIFIES SQL DATA
BEGIN
DECLARE Result INT;
SET Result = 0;
INSERT into MyTable (Id,Name) VALUES(Id,Name);
SELECT Result;
END
That "Id" and "Name" is input parameter and "Result" is output parameter
and create linked server in SQL SERVER and call it like this:
select * from openquery
(
Test,'call mydb.MyPro(''Name'',''16'', #P0);'
)
It works for me :D
Linked Servers and OPENQUERY, Gems to MS SQL Server...that are wolves in sheep clothing. I've found the following solutions to work when dealing with parameters
If the SP is basically just SELECT statements, the move the same to a VIEW and just pass SQL statements via OPENQUERY.
Build the OPENQUERY as a string and then use execute_sql.
You could also see if it works to precede exec with SET FMTONLY ON:
OPENQUERY([LINKSERVER],'SET FMTONLY ON; exec database.user.my_stored_proc ''AT'',''XXXX%'',''1111'',1')
If you try this and it works, you should probably Google FMTONLY+OPENQUERY to get an idea of what it means.
Try this,
SELECT * FROM OPENQUERY(linked_server_name, 'SELECT postgres_procedure_name (parameters)');
I experienced a very similar issue, but my SP wasn't taking any parameters.
I tried experimenting with altering the query sent through the openquery to include 'SET NOCOUNT ON' and 'SET FMTONLY OFF' but this had no difference.
The only solution that worked for my stored procedure was dropping the existing version, and altering the code to specifically 'SET NOCOUNT ON'
After doing this I was able to successfully run my stored proc through my linked server connection.
First of all you have to add hard code text fields then you have to
replace it by your parameters value like FromDate,TillDate,EmpID,CompCode,0,DeptID,DesgId,LocationID,AtnType
DECLARE #startdate varchar(255) = '2019-12-17'
DECLARE #enddate varchar(255) = '2019-12-17'
Set #SQL = 'SELECT * FROM OPENQUERY(' + quotename(#LinkedServer) + ',' + '''' +
'SET FMTONLY OFF; exec [TAP].[dbo].[GetAttendanceList] ' + 'FromDate,TillDate,EmpID,CompCode,0,DeptID,DesgId,LocationID,AtnType,1'')'
You have to replace your parameters values shown below
set #SQL=REPLACE(#SQL,'FromDate',+''''+''''+#startdate+''''+'''')
set #SQL=REPLACE(#SQL,'TillDate',+''''+''''+#enddate+''''+'''')
set #SQL=REPLACE(#SQL,'CompCode',+''''+''''+#CompCode+''''+'''')
set #SQL=REPLACE(#SQL,'AtnType',+''''+''''+''''+'''')
if #EmpID is Null
begin
set #SQL=REPLACE(#SQL,'EmpID','null')
end
if #DeptID is Null
begin
set #SQL=REPLACE(#SQL,'DeptID','null')
end
if #DesgId is Null
begin
set #SQL=REPLACE(#SQL,'DesgId','null')
end
if #LocationID is Null
begin
set #SQL=REPLACE(#SQL,'LocationID','null')
end
print #SQL
exec ( #SQL)