I have written an SQL script which runs fine when executed directly in SQL Management Studio. However, when entering it into Power BI as a source, it reports that it has an incorrect syntax.
This is the query:
EXEC "dbo"."p_get_bank_balance" '2'
However, the syntax is apparently incorrect? See Picture:
Any help is much appreciated.
EDIT ***
When the double quotes are removed (as per Tab Alleman's suggestion):
I found time ago the same problem online on power bi site:
http://community.powerbi.com/t5/Desktop/Use-SQL-Store-Procedure-in-Power-BI/td-p/20269
You must be using DirectQuery mode, in which you cannot connect to data with stored procedures. Try again using Import mode or just use a SELECT statement directly.
In DirectQuery mode, PowerBI automatically wraps your query like so: select * from ( [your query] ), and if you attempt this in SSMS with a stored procedure i.e.
select * from (exec dbo.getData)
You get the error you see above.
The solution is you have to place your stored procedure call in an OPENQUERY call to your local server i.e.
select * from OPENQUERY(localServer, 'DatabaseName.dbo.getData')
Prerequisites would be: enabling local server access in OPENQUERY with
exec sp_serveroption #server = 'YourServerName'
,#optname = 'DATA ACCESS'
,#optvalue = 'TRUE'
And then making sure you use three-part notation in the OPENQUERY as all calls there default to the master database
With "Import" data connectivity mode Stored Procedures work
With "Direct Query" data connectivity mode, the query syntax must be like below:
declare #sqlCommand varchar(100) = 'dbo.p_get_bank_balance'
declare #p1 int = 2
exec #sqlCommand #p1 = #p1
Remerber: max one data source connection with Direct Query. If you want to call much SP, only one can be in Direct Query mode, the others in Import mode
Try using Import instead of Direct Query. It may be showing error cause you are using Temp table in it. Create query using sub query and remove Temp table and try it. Or you can use as Import instead of Direct Query it will work.
Related
I have access to an Access database and within that database are fields filled with TSQL queries. These queries are processed by T-SQL on a server. So when I write these SQL queries and put them into a field for use by the end server, I'm unable to validate the syntax/etc. I could create a temporary query in that Access database, but it's not the same query language. For example, Access would correctly use IIF but TSQL would not (it would instead be CASE).
I don't have direct access to this server with TSQL, is there a way I can validate my T-SQL queries (for syntax and the like)? Perhaps a web tool online?
I should note I do not have access to the SQL server. Only the Access db and that alone. I understand it will not validate table names and the like, I wouldn't expect it to.
Actually, a combination of MattMc3's answer and FremenFreedom's answer should work.
Download SQL Express.
Then, declare the following stored procedure:
create procedure IsValidSQL (#sql varchar(max)) as
begin
begin try
set #sql = 'set parseonly on;'+#sql;
exec(#sql);
end try
begin catch
return(1);
end catch;
return(0);
end; -- IsValidSQL
You can test it with:
declare #retval int;
exec #retval = IsValidSQL 'select iif(val, 0, 1) from t';
select #retval
or with:
declare #retval int;
exec #retval = IsValidSQL 'select val from t';
select #retval
Note: this will catch the IIF() issue. It will not catch anything related to the table structures or column structures. You would need the schema for that and a slightly different approach ("select top 0 * from () t") woudl do it.
You might be able to do something with SQL Fiddle online. However, I would suggest having a local copy of the database.
You can parse your T-SQL to check for valid syntax by executing it on the SQL Server machine with a SET PARSEONLY ON as the first line of your script. It will not validate table or field names, but will provide you with any syntax errors.
The Data Dude (Gert Drapers) describes how to use the built-in SQL Server T-SQL parser in your application here:
Getting to the Crown Jewels
If you want to only check the validity of the SQL statements that you have - this might be a nice way to go, and it doesn't require SQL Server per se to be installed where you run your unit tests.
It's a .NET based approach, and it cannot - of course - validate object names in your database if you're not using a live database - but it can catch syntactical errors in your T-SQL statements.
You can use the NOEXEC option:
SET NOEXEC ON
SELECT 1 AS Test
SET NOEXEC OFF
Is SQL Server Management Studio Express (free download) able to connect to regular SQL Server instances? If so, perhaps you could test the queries there. Even if you could not connect to the actual server, you might be able to create a test version of your database in Express that would at least allow you to catch syntax and naming problems.
If they are fairly static, convert them into stored procedures in the Sql Database and then just call them from access.
Could you please help me with below task. I need to run below query on remote server
UPDATE prod
SET prod.count = ( SELECT SUM(Inv) FROM cost WHERE pID = prod.ID)
WHERE (( SELECT COUNT(id) FROM Cost WHERE pID = prod.ID ) > 0)
I have tried to use OPENROWSET but do not have enough experience working with it and all online examples with OPENROWSET that I saw use only one table. Can you please give me an idea how to modify this query to use OPENROWSET or ideas of any other solutions?
You can use direct linked server or OPENQUERY (linked_server_name ,'your query').
Best way to to this is to create procedure on target instance and use only easy exec on linked server to run procedure.
exec LinkedServer.TargetDB.TargerSc.NewProcedure
Openrowset is used to "open row set" - primary to access remote data, to modify remote data is openquery.
I have access to an Access database and within that database are fields filled with TSQL queries. These queries are processed by T-SQL on a server. So when I write these SQL queries and put them into a field for use by the end server, I'm unable to validate the syntax/etc. I could create a temporary query in that Access database, but it's not the same query language. For example, Access would correctly use IIF but TSQL would not (it would instead be CASE).
I don't have direct access to this server with TSQL, is there a way I can validate my T-SQL queries (for syntax and the like)? Perhaps a web tool online?
I should note I do not have access to the SQL server. Only the Access db and that alone. I understand it will not validate table names and the like, I wouldn't expect it to.
Actually, a combination of MattMc3's answer and FremenFreedom's answer should work.
Download SQL Express.
Then, declare the following stored procedure:
create procedure IsValidSQL (#sql varchar(max)) as
begin
begin try
set #sql = 'set parseonly on;'+#sql;
exec(#sql);
end try
begin catch
return(1);
end catch;
return(0);
end; -- IsValidSQL
You can test it with:
declare #retval int;
exec #retval = IsValidSQL 'select iif(val, 0, 1) from t';
select #retval
or with:
declare #retval int;
exec #retval = IsValidSQL 'select val from t';
select #retval
Note: this will catch the IIF() issue. It will not catch anything related to the table structures or column structures. You would need the schema for that and a slightly different approach ("select top 0 * from () t") woudl do it.
You might be able to do something with SQL Fiddle online. However, I would suggest having a local copy of the database.
You can parse your T-SQL to check for valid syntax by executing it on the SQL Server machine with a SET PARSEONLY ON as the first line of your script. It will not validate table or field names, but will provide you with any syntax errors.
The Data Dude (Gert Drapers) describes how to use the built-in SQL Server T-SQL parser in your application here:
Getting to the Crown Jewels
If you want to only check the validity of the SQL statements that you have - this might be a nice way to go, and it doesn't require SQL Server per se to be installed where you run your unit tests.
It's a .NET based approach, and it cannot - of course - validate object names in your database if you're not using a live database - but it can catch syntactical errors in your T-SQL statements.
You can use the NOEXEC option:
SET NOEXEC ON
SELECT 1 AS Test
SET NOEXEC OFF
Is SQL Server Management Studio Express (free download) able to connect to regular SQL Server instances? If so, perhaps you could test the queries there. Even if you could not connect to the actual server, you might be able to create a test version of your database in Express that would at least allow you to catch syntax and naming problems.
If they are fairly static, convert them into stored procedures in the Sql Database and then just call them from access.
How can I pass parameters in an OLE DB Source to call a table-valued function like:
select * from [dbo].[udf_test](?, ?)
When doing so, I am getting the error:
Parameters cannot be extracted from the SQL command. The provider might not help to parse parameter information from the command. In that case, use the "SQL command form variable" access mode, in which the entire SQL command is stored in a variable.
Syntax error, permission violation, or other nonspecific error (Microsoft SQL Native Client)
Is there another solution than "SQL command from variable"?
Sven
You can use the SQL Command from Variable, it is relatively straightforward. You could build the SQL statement to pass to the Source using a Script transform to edit the variable which holds the SQL. So for example you'd set up a variable called strSQL and make the value
select * from [dbo].[udf_test](?1, ?2)
And then in the script component, replace the ?1 and ?2 values with the parameters you want to pass using string manipulation methods.
It's a little more work in the package but works well in my experience.
This is a little bit of a workaround but it works pretty well. What we do is create a stored procedure called SetVar that will take an input parameter and assign it to a declared out parameter.
Create a procedure called SetVar in the OLE DB source database. It assigns #inputVar to #outVar
CREATE PROC SetVarInt
#inputVar INT ,
#outVar INT OUTPUT
AS
BEGIN
SELECT #outVar = #inputVar;
END
In the SSIS OLE DB source use this SQL:
DECLARE #param1 INT;
EXEC [dbo].[SetVarInt] #inputVar = ?, -- int
#outVar = #param1 OUTPUT -- int
SELECT * FROM [dbo].[GetByKey](#param1)
If nothing happens, the optimizer may have optimized the task away (check package execution log). In this case I will add the following to the end of the OLE DB source SQL, and connect this output to a RowCount task into a dummy variable.
SELECT 1 Done;
If you want to keep it simple, and just have the query in the OLDDB source without using other tricks, you can achieve that by writing the entire T-SQL code needed to get it done e.g.
declare #var1 as int = ?;
declare #var2 as datetime = ?;
select *
from [dbo].[udf_test](#var1, #var2);
Doing it like that you do not need to have a separate task in SSIS to build the query and assign the parameteres, it all stays in the same place, and therefore easier to write, and even more important easier to understand by the person who will need to support this after you.
Using SQL Server 2005, I'd like to run a stored procedure and insert all of the results into a new table.
I'd like the new table to have its columns automatically configured based upon the data returned by the stored procedure.
I am familiar with using the SELECT ... INTO syntax:
SELECT * INTO newtable FROM oldtable
Is this possible?
Edit for clarification: I'm hoping to accomplish something like:
Select * INTO newtable FROM exec My_SP
The only way to do this is w/ OPENROWSET against the local server:
SELECT * INTO #temp
FROM OPENROWSET (
'SQLOLEDB'
, 'Server=(local);TRUSTED_CONNECTION=YES;'
, 'SET FMTONLY OFF EXEC database.schema.procname'
) a
But this is kind of a last-ditch-gotta-do-it-damn-the-consequences kind of method. It requires elevated permissions, won't work for all procedures, and is generally inefficient.
More info and some alternatives here: http://www.sommarskog.se/share_data.html
This seems like a horrible design. You're really going to create a new table to store the results of a stored procedure, every time the stored procedure is called? And you really can't create the table in advance because you have absolutely no idea what kind of output the stored procedure has? What if the stored procedure returns multiple resultsets? What if it has side effects?
Okay, well, if that's what you really want to do...
One way to accomplish this is to use your local server as a linked server and utilize OPENQUERY. First you need to make sure your local server is configured for data access:
EXEC sp_serveroption 'local server name', 'DATA ACCESS', true;
Then you can do something like this:
SELECT * INTO dbo.newtable
FROM OPENQUERY('local server name', 'EXEC yourdb.dbo.yourproc;');
PS How are you going to write code that is going to perform SELECT INTO into a new table name every time (because you can only do SELECT INTO once)? Dynamic SQL? What happens if two users run this code at the same time? Does one of them win, and the other one just gets an error message?
A variation of the same is
create table somename
select * from wherever;