'Invalid column' error from stored procedure query - sql-server

I have a problem with a query to store results from a stored procedure in a temporary table. See below for a simplified version of the query itself:
USE [ADataBaseName]
GO
CREATE TABLE #temp(
SrcUD16 VARCHAR(200))
DECLARE #return_value int
INSERT INTO #temp(
SrcUD16)
EXEC #return_value = [dbo].[AStoredProcedure]
#PartKey = 100,
#Entity_Name = N'SomeEntityName,
#PeriodDesc = N'QA - 2014',
#CategoryKey = 12
SELECT * FROM #temp
GO
The stored procedure creates two other temporary tables to be joined in a Select statement:
SELECT SrcUD16 FROM #temp2 LEFT JOIN #temp3
ON #temp2.MinMaxCIC = #temp3.SrcUD15
Executing the first statement above will give me the following error:
'Invalid column name 'SrcUD16'
However, manually executing the stored procedure does yield the expected results for the field SrcUD16. I can also change the fieldname from SrcUD16 to SrcUD15 which results in a working query albeit incorrect column heading (i.e. ScrUD16 data with 'SrcUD15' as heading).
I strongly suspect this error has something to do with the order in which the temp tables are created and what the query recognizes as allowed field headings. Perhaps someone with better understanding has soem pointers for me?
Thanks in advance

Related

How to use table input parameter for MERGE command in Oracle Stored Procedure

I am currently trying to write a stored procedure that inserts or updates multiple rows into my database. I pass the rows via a table input parameter, but I am stuck on how to pass those rows to the MERGE-command.
This command is working fine:
MERGE INTO dbo.EntryTable a
USING (SELECT 'abc' "keyColumn", 'def' "valueColumn" FROM DUAL) b
ON (a."keyColumn" = b."keyColumn")
WHEN MATCHED THEN UPDATE SET a."valueColumn" = b."valueColumn"
WHEN NOT MATCHED THEN
INSERT ("keyColumn","valueColumn")
VALUES(b."keyColumn",b."valueColumn);
To get this into a stored procedure I created a table type:
CREATE OR REPLACE TYPE entry_type AS OBJECT
(
"keyColumn" NVARCHAR2(3),
"valueColumn" NVARCHAR2(3)
);
CREATE OR REPLACE TYPE entry_type_list AS TABLE OF entry_type;
But as soon as I try to use it in a stored procedure like this:
CREATE OR REPLACE PROCEDURE set_entry_list (entries entry_type_list) AS
BEGIN
MERGE INTO dbo.EntryTable a
USING (SELECT * FROM entry_type_list) b
ON (a."keyColumn" = b."keyColumn")
WHEN MATCHED THEN UPDATE SET a."valueColumn" = b."valueColumn"
WHEN NOT MATCHED THEN
INSERT ("keyColumn","valueColumn")
VALUES(b."keyColumn",b."valueColumn);
END;
I am getting errors like this when creating the stored procedure:
LINE/COL ERROR
3/5 PL/SQL: SQL Statement ignored
4/26 PL/SQL: ORA-00942: table or view does not exist
I tried to find documentation on how to do this but I am currently out of ideas where to look.
If you are using 11g, you would still need the table operator in your query
SELECT * FROM TABLE( entry_type_list )
So your MERGE statement would be something like
MERGE INTO dbo.EntryTable a
USING (SELECT * FROM table( entry_type_list ) ) b
ON (a."keyColumn" = b."keyColumn")
WHEN MATCHED THEN UPDATE SET a."valueColumn" = b."valueColumn"
WHEN NOT MATCHED THEN
INSERT ("keyColumn","valueColumn")
VALUES(b."keyColumn",b."valueColumn);

Retrieve column definition for stored procedure result set that uses temp table

I am trying to retrieve column definitions for a stored procedure using the following query:
exec sp_describe_first_result_set #tsql = N'EXEC #return_value = [dbo].[foo]
#DATABASENAME = dbname,
#TABLENAME = tblname,
#DATEFROM = N''20170101'',
#DATETO = N''20170201'''
And I get the following response:
Msg 11526, Level 16, State 1, Procedure sp_describe_first_result_set, Line 1
The metadata could not be determined because statement 'INSERT INTO #Tables(CubeSchema,TableName,DateFilterColumn,SelectColumns) SELECT 'Col1','Col2' in procedure 'foo' uses a temp table
Is there a workaround for this issue?
Edit: I have not the rights to view and/or alter the stored procedures, so unfortunately solutions of this sort won't work.
Without altering your stored procedure the answer is MAYBE.
The option you are using ('sp_describe_first_result_set') wont work with the temp table, since you are using an INSERT statement.
If you would alter the INSERT statement to a SELECT INTO statement it might work for storing the data into the temp table, but you still wouldn't get your data out of it, since it isn't available. I am not sure about the internals of 'sp_describe_first_result_set', but it looks like it is using the SET FMTONLY ON option, which will fail because of the temp table.
So, if you want to avoid this, alter the stored procedure to use a table variable instead of a temp table (#table vs #table).
If you are not limited to SQL Server and you can program your way around this in a programming language (for example .Net using ADO.Net), you are able to use the GetSchemaTable method of the ExecuteReader result, like this:
var reader = sqlCommand.ExecuteReader();
var schemaTable = reader.GetSchemaTable();
Hope it helps!

TSQLT Returning Results from a Stored Procedure

In TSQLT, I'm trying to return a result from a stored procedure and add it to a variable so that I can assert if it matches my expected result.
I've seen loads of examples of returning results from functions but none where a stored procedure is called.
Does anybody have examples that they could share?
Thanks in advance
If you want to get a variable back from a stored procedure one way to do this is to use an out parameter
CREATE PROC MyTest
(#myVar int output)
AS
BEGIN
SET #myVar = 10
END
GO
DECLARE #x int
EXEC MyTest #myVar=#x output
SELECT #x
If you are getting a result set back from the stored procedure, here is an example from a tSQLt test that I wrote. I haven't bothered with the whole test because this should give you what you need.
CREATE TABLE #Actual (SortOrder int identity(1,1),LastName varchar(100), FirstName varchar(100), OrderDate datetime, TotalQuantity int)
-- Act
INSERT #Actual (LastName, FirstName, OrderDate, TotalQuantity)
EXEC Report_BulkBuyers #CurrentDate=#CurrentDate
The trick here is that you have to create the #actual table first. It should contain the same columns as what is returned from the stored procedure.
Just as an aside, you may have noticed I have a SortOrder column in the #actual table. This is because I was interested in testing the order of the data returned for this specific report. EXEC tSQLt.AssertEqualsTable will match rows like for like, but does not match the order in which the rows appear in the expected and actual so the way to ensure the order is to add a SortOrder column (which is an identity column) to both the #expected and #actual
Have a look here:
http://technet.microsoft.com/en-us/library/ms188655.aspx
Lots of examples about returning values from a stored procedure. At the bottom of the page there is also an example about evaluating a return code.
its actually really simple.
declare #variable int
exec #variable = _Stored_Procedure

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

Invalid column name "USER_SOURCE"

I have a stored procedure which is returning a result in an xml #Data output parameter
To assign data in xml code is
SELECT #data= (
SELECT DISTINCT
CONVERT(varchar(2),u.USER_SOURCE ) + '~' +
CONVERT(varchar(20), u.[USER_ID]) + '-' +
CONVERT(varchar(10), u.DEALER_ID) as USER_DEALER_ID
FROM #users u FOR XML RAW('users'))
When I exec the procedure in SQL Server Mgmt Studio, I can see the result OK.
This procedure is been called from another procedure, and that parent procedure is used in SSRS.
In SSRS I am getting error
Query execution failed for dataset 'DataSet1'. Invalid column name
'USER_SOURCE'. Invalid column name 'USER_ID'. Invalid column name
'DEALER_ID'.
Could you please help?
Thanks,
Chetan
Here's a script which I think reproduces a problem identical to yours:
CREATE PROCEDURE TestTmpTable
#value varchar(20)
AS
BEGIN
CREATE TABLE #test (id int IDENTITY, value varchar(20));
INSERT INTO #test (value) VALUES (#value)
SELECT * FROM #test;
DROP TABLE #test;
END
GO
CREATE TABLE #test (id int IDENTITY, value2 varchar(20));
EXEC TestTmpTable 'some text';
SELECT * FROM #test;
DROP TABLE #test;
GO
DROP PROCEDURE TestTmpTable
As you can see, there are two #test tables here, one is created in the stored procedure, the other one in the batch that invokes the stored procedure. They have different structures: one has a column named value, the other a column named value2. If you run the script, you'll see this error:
Msg 207, Level 16, State 1, Procedure TestTmpTable, Line 6
Invalid column name 'value'.
I can't point you to a relevant documentation article at the moment, but to me it is evident enough that some preliminary name checking is taking place immediately before the execution of the SP. At that stage, a discrepancy between the column names referenced in the stored procedure and those actually present in the already existing table is revealed, which renders the execution impossible.
If you change value2 to value, the script will work without any problem, and there will be two row sets in the output, one with the 'some text' value, the other empty. And of course the script will work if you remove all parts related to the external #test table.
So, check the places where your procedure is called to see if any other #users table can be existing by that moment, and if so, amend the issue according to your situation.

Resources