Openquery for serverlink exceedes 8000 characters - sql-server

I want to create a view as follows:
CREATE view [dbo].[test] as
SELECT TEST.*
FROM OPENQUERY([MyServerLink],'LONGSELECTQUERY') as TEST;
The SELECT statement exceeds 8000 characters long which gives me that error:
SQL Error [103] [S0001]: The character string that starts with 'SELECT ...' is too long. Maximum length is 8000.
How can I overcome that and create my view?

You can create a temporary table on the linked server and then use the temporary table
Example (MySQL)
EXEC('DROP TEMPORARY TABLE IF EXISTS TEMP_LONGSELECTQUERY') AT MyServerLink
EXEC('
CREATE TEMPORARY TABLE TEMP_LONGSELECTQUERY AS
LONGSELECTQUERY
') AT MyServerLink
SELECT * FROM OPENQUERY(MyServerLink, 'SELECT * FROM TEMP_LONGSELECTQUERY')
But, if the linked server is also a MSSQL Server you can make a select refering to the Server.Database.Schema.Table:
SELECT
/******/
FROM MyServerLink.master.dbo.xxx x
join MyServerLink.master.dbo.yyy y /*****/

Related

Temporary table not created from dynamic query execution

If I run this dynamic query:
declare #test nvarchar(1000) = 'select * into #tmp7 from bauser'
execute(#test)
and then try to query #tmp7 with:
select * from #tmp7
error is thrown:
Invalid object name '#tmp7'.
However if I run the same query manually:
select * into #tmp7 from bauser
Everything is OK. Temporary table is created and filled with results.
Why is it not working with dynamic query execution?
SCOPE!
The temporary table exists only in the scope of the dynamic executed query
If you do want to make the select put it inside the dynamic query
declare #test nvarchar(1000) = 'select * into #tmp7 from bauser
select * from #tmp7'
execute(#test)
Also you can check if a such object exists by using this
select * from sys.sysobjects so where so.name like '%tmp7%'
See this similar question
SQL Server 2005 and temporary table scope
Edit
A temp table IS A TABLE so yes you can add columns, indexes, etc. Those tables resides in fact in the TempDB database and you can even "find" them (they can be seen with strange long names) but they are destroyed after the execution of your EXEC.
Maybe your problem is to try the dynamic approach or is not related to your question at all. Try to post a new question what you got and what you need to do to get further assistance.
If you create temp table using dynamic SQL, it will not be available out of dynamic SQL scope.
You need to create it out of dynamic SQL and then use INSERT INTO to populate the table.
-- use this trick to create the temp table easily.
SELECT * INTO #tmp7
FROM bauser
WHERE 1=2
declare #test nvarchar(1000) = 'insert into #tmp7 select * from bauser'
execute(#test)

SELECT * INTO [newdatabase].[table] FROM [otherdatabase].[table]

I'm trying to figure out how to create a copy of a table from one linked server to another inside Management Studio. I have both linked servers created, and I can query them. However, one is a SQL Server instance and the other is a ODBC connection to a QuickBooks QODBC connection.
When querying the SQL Server instance I run a query like this
SELECT *
FROM [MYSERVERNAME\SQLSERVICEINSTANCE].[DATABASENAME].[DBO].[TABLENAME]
When querying the QODBC QuickBooks database I run a query like this
SELECT *
FROM OPENQUERY(QUICKBOOKS, 'SELECT * FROM Invoice')
How can I select * into SQLSERVER.Invoices FROM QUICKBOOKS.Invoices?
select * into SQLSERVER.Invoices FROM QUICKBOOKS.Invoices is actually pretty close to what you want.
insert into [DATABASENAME].[DBO].[TABLENAME]
(column1, columns2)
SELECT column1, columns2
FROM OPENQUERY(QUICKBOOKS, 'SELECT * FROM Invoice')
Now I guess you want to do this regularly? The most straightforward way is to to run this first to clear the target table:
TRUNCATE TABLE [DATABASENAME].[DBO].[TABLENAME]
If you want to make an exact copy use this:
USE [DATABASENAME]
IF EXISTS (
SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[DBO].[TABLENAME] ')
AND type in (N'U')
)
DROP TABLE [DBO].[TABLENAME]
SELECT *
into [DBO].[TABLENAME]
FROM OPENQUERY(QUICKBOOKS, 'SELECT * FROM Invoice')
You can pop any of these scripts into a sql agent job to refresh on a regular basis

SQL Server sp_msforeachtable

I am having a problem with using the sp_msforeachtable SQL Server stored procedure.
I want to have output of EXECUTE statement in one table using following SQL query:
TRUNCATE TABLE DaneOSpuscie --clear the table
EXEC sp_msforeachtable
'INSERT INTO [DaneOSpuscie] ([Database name], [Table name])
SELECT ''?'', name
FROM [sys].[columns]
WHERE [sys].[columns].[name] LIKE ''%[Tt][aA][pP12]%'' '
This throws an error
String or binary data would be truncated
for each table.
Additional info: Table "DaneOSpuscie" has only two columns: Database name, Table name of type varchar.
Check your table structure.
Check your max length of your objects.
Compare it. Set your columns in your table to real max length or use maximal system object length - sysname = nvarchar(128).

Dynamically created temporary table does not persist

I want to create a temporary table in a dynamic query and use it afterwards. It will be created from a permanent table:
create table t (a integer);
insert into t values (1);
And the temp table creation is like this:
declare #command varchar(max) = '
select *
into #t
from t
;
select * from #t;
';
execute (#command);
When the #command is executed the select from the temporary table works.
Now if I select from the temporary table an error message is shown:
select * from #t;
Invalid object name '#t'
If the temporary table is created outside of the dynamic query it works:
select top 0 *
into #t
from t
declare #command varchar(max) = '
insert into #t
select *
from t
';
execute (#command);
select * from #t;
Is it possible to persist a dynamically created temporary table?
You are close in your assumption that EXECUTE is carried out in a different session.
According to the MSDN here
Executes a command string or character string within a Transact-SQL
batch
So your temporary table only exists inside the scope of the SQL executed by the EXECUTE command.
You can also create global temporary tables. For example, ##MyTemp.
But, global temporary tables are visible to all SQL Server connections.

How to create dynamic stored procedure in SQL Anywhere?

I'm having an issue with creating dynamic sql statement in SQL Anywhere.
CREATE PROCEDURE pplAnalysis
AS
BEGIN
DECLARE #Sql NVARCHAR(4000)
SELECT #Sql = "select * from cds.ppl"
EXECUTE(#Sql)
END
When I execute this procedure, I get an Column 'select * from cds.ppl' not found error.
Can you please tell me what am I doing wrong?
The issue had to do with syntax and the RESULT clause; after adding semicolons, RESULT clause, and used SET to initialize the Sql variable, here is what worked (tested in SQL Anywhere Network Server Version 12.0.1):
drop proc pplAnalysis;
CREATE PROCEDURE pplAnalysis()
RESULT (cnot CHAR(5), cnull CHAR(5), vnot VARCHAR(5), vnull VARCHAR(5), explanation VARCHAR(50))
BEGIN
DECLARE #Sql NVARCHAR(4000);
SET #Sql = 'select cnot, cnull, vnot, vnull, explanation from dbo.spaces';
EXECUTE ( #Sql );
END;
spaces is a table in the dbo schema and those columns are the same type specified in RESULT
Tested these two ways to execute the procedure and both returned result:
call pplAnalysis();
cnot cnull vnot vnull explanation
----- ----- ----- ----- --------------------------------------------------
Execution time: 0.027 seconds
Procedure completed
or
exec pplAnalysis;
cnot cnull vnot vnull explanation
----- ----- ----- ----- --------------------------------------------------
Execution time: 0.018 seconds
For more details:
Returning result sets from procedures
Create procedure statement
Try first saving the result of the query in a temporal table, and then do a SELECT from the temporal table:
SELECT #Sql = "select into #temp * from cds.ppl"
EXECUTE(#Sql)
SELECT * FROM #temp
Use single quotes.
SELECT #Sql = 'select * from cds.ppl'
After some research, I have edited my answer.
Regarding the EXECUTE ( string-expression ) statement, yes you have to use single quotes instead of double quotes for the string expression. This page mentions:
It lets you execute dynamically prepared statements, such as
statements that are constructed using the parameters passed in to a
procedure. Literal strings in the statement must be enclosed in single
quotes, and the statement must be on a single line.
Which will eliminate the column not found error but the procedure will return this other error:
Result set not permitted in '<batch statement>'
Same error returned when trying to execute this statement alone:
execute ('select * from sysusers')
With probable cause:
You attempted to execute a SELECT statement in a context where a
result set is not permitted.
See my most recent answer for the solution.
And regarding schemas, here's how to refer to objects:
It is always good practice to refer to database objects by a schema
name and the object name, separated by a period (.). For a complete example, to SELECT records from the Employee table in the HumanResources schema of the current database would look like:
SELECT * FROM HumanResources.Employee
To reference an object located in a remote database, the fully
qualified object name includes the server name and the database name.
For example, to SELECT records from the Employee table in the
HumanResources schema in the AdventureWorks database on MyServer would
look like:
SELECT * FROM MyServer.AdventureWorks.HumanResources.Employee
I tested that in SQL Anywhere 12 and it works the same. And even though I was not familiar with schemas, what I'm suggesting you below is actually using schemas, dbowner would be the schema name:
1) select * from dbname.dbowner.tablename
2) select * from dbowner.tablename
3) select * from dbname..tablename (assumes table exists in the dbo schema)
Bottom line.... In your select statement cds.ppl has to be a table named ppl created in the cds schema.
Or if cds is your database name and ppl your table name created in the dbo schema, you are missing a dot:
select * from cds..ppl

Resources