Won't able to Pass the Table name Dynamically using sp_execute_external_script using R Script - sql

I create this query, This will work fine On SQL Server
When am using this query in inside sp_execute_external_script using R Script
I won't able to pass '+#TableName+' please check and Suggest some Solution
// This code Work fine in SQL
Declare #TableName nvarchar(max)
Declare #Plant nvarchar(max) ='XXX'
Declare #Tub nvarchar(max) ='YYY'
Set #TableNameByModelName = 'Ref_curve' -- Need This from UI
exec (N'SELECT
p.[Plant]
,P.[Tub]
,r.[Power]
FROM [dbo].[Analysis_Curve] as P
INNER join [P_Analysis].dbo.'+#TableName+' AS r on r.Speed = P.Speed
where P.Plant= '''+#Plant+'''
AND P.Tub = '''+#Tub+'''')
// This code is Using R script Need Suggestion here
Alter procedure [dbo].[Pass_Dynamic_TableName]
( #Plant1 nvarchar(50),
#Tub1 nvarchar(50)
)
As
Begin
Declare #TableName NVARCHAR(200);
Set #TableName = 'Ref_curve'
EXEC sp_execute_external_script
#language =N'R',
#script=N'df <- as.data.frame(InputDataSet);
OutputDataSet <-df'
,#input_data_1 =N'SELECT
p.[Plant]
,P.[Tub]
,r.[Power]
FROM [dbo].[Analysis_Curve] as P
INNER join [P_Analysis].dbo.#TableName AS r on r.Speed = P.Speed
where P.Plant= #Plant22
AND P.Tub = #Tub22'
,#params = N'#Plant22 varchar(50) OUTPUT, #Tub22 varchar(50) OUTPUT'
,#Plant22 = #Plant1
,#Tub22 =#Tub1
WITH RESULT SETS Undefined;
END

Could you try this.
Alter procedure [dbo].[Pass_Dynamic_TableName]
( #Plant1 nvarchar(50),
#Tub1 nvarchar(50)
)
As
Begin
Declare #TableName NVARCHAR(200);
Set #TableName = 'Ref_curve'
DECLARE #input_script NVARCHAR(MAX) =N'SELECT
p.[Plant]
,P.[Tub]
,r.[Power]
FROM [dbo].[Analysis_Curve] as P
INNER join [P_Analysis].dbo.' + QUOTENAME(#TableName) + ' AS r on r.Speed = P.Speed
where P.Plant= #Plant22
AND P.Tub = #Tub22'
EXEC sp_execute_external_script
#language =N'R',
#script=N'df <- as.data.frame(InputDataSet);
OutputDataSet <-df'
,#input_data_1 = #input_script
,#params = N'#Plant22 varchar(50), #Tub22 varchar(50) '
,#Plant22 = #Plant1
,#Tub22 =#Tub1
WITH RESULT SETS Undefined;
END

Related

SQL Server output param truncated where it is too long

I have 4 stored procedures.
The following is used to be invoked by C#:
ALTER PROCEDURE [dbo].[sp_retrieveResourceShell]
AS
BEGIN
SET NOCOUNT ON
DECLARE #result NVARCHAR(MAX)
EXEC [dbo].[sp_retrieveResTree]
#pid = NULL,
#ret = #result OUTPUT
***select*** #result
END
These are internal stored procedures:
ALTER PROCEDURE [dbo].[sp_retrieveResTree]
(#pid UNIQUEIDENTIFIER,
#ret NVARCHAR(MAX) OUTPUT)
AS
BEGIN
DECLARE #mdlId UNIQUEIDENTIFIER,
#mdlGroup NVARCHAR(MAX)
DECLARE mdlCursor CURSOR FOR
......
DECLARE #subRet NVARCHAR(MAX),
#viewRet NVARCHAR(MAX)
EXEC [dbo].[sp_retrieveResTree]
#pid = #mdlId,
#ret = #subRet OUTPUT
EXEC dbo.sp_retrieveResView
#mdlId = #mdlId,
#ret = #viewRet OUTPUT
SET #mdlGroup = #mdlGroup + FORMATMESSAGE('{"Id":"%s","Name":"%s","Subs":%s,"Views":%s},'...)
.......
SET #ret = FORMATMESSAGE('[%s]',#mdlGroup)
END
ALTER PROCEDURE [dbo].[sp_retrieveResView]
(#mdlId UNIQUEIDENTIFIER,
#ret NVARCHAR(MAX) OUTPUT)
AS
BEGIN
SET #ret = FORMATMESSAGE('[%s]',#viewGroup)
END
When I invoke sp_retrieveResourceShell like this:
DECLARE #return_value int
EXEC #return_value = [dbo].[sp_retrieveResourceShell]
SELECT 'Return Value' = #return_value
I can get a truncated string with ellipsis at the string tail.
how to get the full string without ellipsis?
update
Changed formatmessage function to string concatenation likes
SET #mdlGroup = #mdlGroup + '{"Id":"' + CAST(#mdlId AS CHAR(36))+ '","Name":"' + #mdlName + '","Subs":' + #subRet + ',"Views":' + #viewRet +'},'
when using string concatenation , likes
SET #ret = N'[' + #mdlGroup + N']'
and refernce to [n]varchar(max) + [n]varchar(max)
i got the right full string . Thanks to #MartinSmith at the same time .

How to define a complex return type without a table?

I have a stored procedure with dynamic sql that I need to return an OBJECT_RESULT type. I am trying to build the complex type within visual studio through EF. The problem, I believe, is coming from the fact that the table is one of the parameters of the proc. So when EF tries to build the type and the table is null, I get the error that the selected stored proc returns no columns. I have tried setting FMTONLY off and specified the actual columns in the select statement. Any way I can achieve this? The proc:
SET FMTONLY OFF
GO
ALTER PROCEDURE [dbo].[GetFormFieldCDC2]
(
#formfieldId INT,
#C___operation INT,
#C___start_lsn binary(10),
#schemaname sysname,
#tablename sysname
)
AS
SET NOCOUNT ON;
--IF (OBJECT_ID(QUOTENAME(#schemaname) + '.' + QUOTENAME(#tablename)) IS NULL)
-- THROW 50000, 'Table not found', 0;
DECLARE #sql AS NVARCHAR(MAX) = '
SELECT [__$start_lsn]
,[__$end_lsn]
,[__$seqval]
,[__$operation]
,[__$update_mask]
,[ID]
,[LookupList]
,[LookupColumns]
,[LookupAdditionalColumns]
,[FormFieldsID]
,[DateAdded]
,[DateEdited]
,[CreatedBy]
,[EditedBy]
,[__$command_id]
FROM ' + QUOTENAME(#schemaname) + '.' + QUOTENAME(#tablename) + '
WHERE __$start_lsn = #C___start_lsn
AND __$operation = #C___operation
AND FormFieldsID = #formfieldId;
';
EXEC sp_executesql #SQL,
N' #formfieldId INT,
#C___operation INT,
#C___start_lsn binary(10)',
#formfieldId = #formfieldId,
#C___operation = #C___operation,
#C___start_lsn = #C___start_lsn;
Don't set FMTONLY off. That's an old hack that is no longer necessary. Instead, explicitly declare the shape of the resultset, using EXECUTE ... WITH RESULT SETS when you execute the dynamic SQL. Like this:
CREATE OR ALTER PROCEDURE [dbo].[GetFormFieldCDC2]
(
#formfieldId INT,
#C___operation INT,
#C___start_lsn binary(10),
#schemaname sysname,
#tablename sysname
)
AS
BEGIN
/*
declare #object_id int = object_id('GetFormFieldCDC2')
select * from sys.dm_exec_describe_first_result_set_for_object(#object_id,0)
*/
SET NOCOUNT ON;
--IF (OBJECT_ID(QUOTENAME(#schemaname) + '.' + QUOTENAME(#tablename)) IS NULL)
-- THROW 50000, 'Table not found', 0;
DECLARE #sql AS NVARCHAR(MAX) = '
SELECT [__$start_lsn]
,[__$end_lsn]
,[__$seqval]
,[__$operation]
,[__$update_mask]
,[ID]
,[LookupList]
,[LookupColumns]
,[LookupAdditionalColumns]
,[FormFieldsID]
,[DateAdded]
,[DateEdited]
,[CreatedBy]
,[EditedBy]
,[__$command_id]
FROM ' + QUOTENAME(#schemaname) + '.' + QUOTENAME(#tablename) + '
WHERE __$start_lsn = #C___start_lsn
AND __$operation = #C___operation
AND FormFieldsID = #formfieldId;
';
EXEC sp_executesql #SQL,
N' #formfieldId INT,
#C___operation INT,
#C___start_lsn binary(10)',
#formfieldId = #formfieldId,
#C___operation = #C___operation,
#C___start_lsn = #C___start_lsn
WITH RESULT SETS
(
(
[__$start_lsn] binary(10)
,[__$end_lsn] binary(10)
,[__$seqval] binary(10)
,[__$operation] int
,[__$update_mask] varbinary(128)
,[ID] int
,[LookupList] varchar(max)
,[LookupColumns] varchar(max)
,[LookupAdditionalColumns] varchar(max)
,[FormFieldsID] int
,[DateAdded] datetime
,[DateEdited] datetime
,[CreatedBy] varchar(200)
,[EditedBy] varchar(200)
,[__$command_id] int
)
);
END
Then
declare #object_id int = object_id('GetFormFieldCDC2')
select * from sys.dm_exec_describe_first_result_set_for_object(#object_id,0)
Will return the resultset metadata.

Pass a parameter to a parameterized query?

I need to get a query from a database table that contains a parameter. Then use that query to update another table but I need to be able to pass another parameter to that update statement.
declare #locnum int
set #locnum = 032
declare #tempPersonID int
set #tempPersonID = 10008
declare #passwordQuery varchar(max)
set #passwordQuery = (select passwordQuery from location where locationNum = #locnum)
select #passwordQuery
update tempPerson
set [password] = #passwordQuery
where tempPersonID = #tempPersonID
select *
from tempPerson
select #passwordQuery returns (select left(firstname,1) + left(lastname,1) + custom as [password] from tempPerson where tempPersonID = #tempPersonID). I need to able to use the #tempPersomID parameter in this query and the where statement.
Firstly, as you are updating the record that you are selecting the information from you only need the following as your #passwordQuery:
left(firstname,1) + left(lastname,1) + [custom]
Then the following code takes your code and adapts it for dynamic SQL:
declare #locnum int = 032, #tempPersonID int = 10008, #passwordQuery varchar(max), #sql nvarchar(max), #params nvarchar(max);
select #passwordQuery = passwordQuery from [location] where locationNum = #locnum;
-- select #passwordQuery
set #sql = 'update tempPerson set [password] = ' + #passwordQuery
+ ' where tempPersonID = #tempPersonID';
set #params = '#tempPersonID int';
execute sp_executesql #sql, #params, #tempPersonID = #tempPersonID;
select *
from tempPerson
You Can Execute Dynamic SQL Statements with parameter using either the EXEC or sp_ExecuteSQL Statements.
In your Case, The sp_ExecuteSQLseems more suitable. The Syntax for the same is as below
sp_executesql [ #stmt = ] statement
[
{ , [ #params = ] N'#parameter_name data_type [ OUT | OUTPUT ][ ,...n ]' }
{ , [ #param1 = ] 'value1' [ ,...n ] }
]
So Your Entire Script can be re-written as below :
DECLARE #locnum INT
#tempPersonID INT,
#passwordQuery VARCHAR(MAX),
#params VARCHAR(500),
#ParamOut VARCHAR(500)
SELECT
#locnum = 032,
#tempPersonID = 10008,
#params = N'#tempPersonID INT,#MyPwd VARCHAR(500) OUTPUT'
SELECT
#passwordQuery = 'SET #MyPwd = ('+passwordQuery+')'
FROM Location
WHERE LocationNum = #locnum
sp_ExecuteSQL(#passwordQuery,#params,#tempPersonID,#MyPwd = #ParamOut OUTPUT )
UPDATE tempPerson
SET
[password] = #ParamOut
WHERE tempPersonID = #tempPersonID
select *
from tempPerson

Store the result of a Dynamic Query in a variable

I know this question has been asked, and I already found some solutions in internet.. but I still can not make it work properly.
So.. I have to make a SELECT query and store the result in a variable (I DONT want a table variable).
My problem is that the name of the table is also a variable. The table name changes accordingly to a WHILE, here is my code:
DECLARE #numRecord INT;
DECLARE #maxMacNumber INT;
SET #maxMacNumber = 500;
DECLARE #mac INT;
SET #mac = 0;
DECLARE #res FLOAT;
DECLARE #ap INT;
SET #ap = 0;
DECLARE #apString VARCHAR(2);
DECLARE #numRecordString VARCHAR(20);
DECLARE #tablename VARCHAR(500);
DECLARE #sql NVARCHAR(500);
DECLARE #varDefinition NVARCHAR(200);
WHILE #mac <= #maxMacNumber
BEGIN
SET #numRecord = 6 + #mac * 390;
SET #ap = 0;
WHILE #ap < 2
BEGIN
SELECT #apString = CONVERT(VARCHAR,#ap);
SELECT #numRecordString = CONVERT(VARCHAR, #numRecord);
SELECT #rssiString = CONVERT(VARCHAR, #rssi);
SET #tablename = 'APDB.dbo.AP' + #apString;
SET #sql = 'SELECT RSSI FROM ' + #tablename + ' WHERE ID=' + #numRecordString;
SET #varDefinition = N'#res FLOAT OUTPUT';
EXEC sp_executesql #sql, #varDefinition, #res = #res OUTPUT;
PRINT #res;
-- HERE I WILL DO SOMETHING WITH #res
END;
END;
The problem is that it doesn't print anything when I do PRINT #res...
This is the relevant SQL code:
SET #sql = 'SELECT RSSI FROM ' + #tablename + ' WHERE ID=' + #numRecordString;
SET #varDefinition = N'#res FLOAT OUTPUT';
EXEC sp_executesql #sql, #varDefinition, #res = #res OUTPUT;
PRINT #res;
You are never setting #res in the SQL. Try this:
SET #sql = 'SELECT #res = RSSI FROM ' + #tablename + ' WHERE ID=' + #numRecordString;
SET #varDefinition = N'#res FLOAT OUTPUT';
EXEC sp_executesql #sql, #varDefinition, #res = #res OUTPUT;
PRINT #res;

Define a SQL variable with Database Name

With this T-SQL query I define a variable #InDate with some date.
SET
#InDate = (SELECT MIN(bt.CreateDate) AS [INDATE]
FROM
mydatabase.dbo.BuyTransaction bt
LEFT JOIN
mydatabase.dbo.TransactionExtraFields tef ON bt.TransDocument = tef.TransDocument
AND bt.TransSerial = tef.TransSerial
AND bt.TransDocNumber = tef.TransDocNumber
AND ExtraFieldID = 1
WHERE
bt.TransDocument = 'FRM' AND tef.TextAnswer = #NumPI
AND bt.TransStatus = 0)
But now I need to change the Database name by another variable. I try something like that to make a string in a variable which will be executed
SET #InDate = '(SELECT MIN(bt.CreateDate) AS [INDATE]
FROM mydatabase.dbo.BuyTransaction bt
LEFT JOIN mydatabase.dbo.TransactionExtraFields tef ON bt.TransDocument = tef.TransDocument AND bt.TransSerial = tef.TransSerial AND bt.TransDocNumber = tef.TransDocNumber AND ExtraFieldID = 1
WHERE bt.TransDocument = ''FRM'' AND tef.TextAnswer = '''+#NumPI+''' AND bt.TransStatus = 0)'
EXECUTE #InDate
But my problem is how can I get the execute result into a variable again. Something like SET #InDate2 = EXECUTE #InDate is not working...
Any idea?
Use sp_executesql. I think the syntax in your case is something like:
declare #InDate date;
declare #sql nvarchar(max);
set #sql = N'SELECT #InDate = MIN(bt.CreateDate)
FROM mydatabase.dbo.BuyTransaction bt
LEFT JOIN mydatabase.dbo.TransactionExtraFields tef ON bt.TransDocument = tef.TransDocument AND bt.TransSerial = tef.TransSerial AND bt.TransDocNumber = tef.TransDocNumber AND ExtraFieldID = 1
WHERE bt.TransDocument = ''FRM'' AND tef.TextAnswer = '''+#NumPI+''' AND bt.TransStatus = 0';
exec sp_executesql #sql, N'#InDate date output', #InDate = #InDate output;
You can also make #NumPI a parameter as well.
The documentation for sp_executesql is here.
I have done this type of issue.
Please check the sample code. Its working for me. Please change according.
DECLARE #SQLString NVARCHAR(500)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #IntVariable INT
DECLARE #Lastlname varchar(30) = 'col10 ' -- this variable use for input in sp
SET #SQLString = N'SELECT #LastlnameOUT = '+#Lastlname+'
FROM TempStoreExcelData '
SET #ParmDefinition = N'#level tinyint,
#LastlnameOUT varchar(30) OUTPUT'
SET #IntVariable = 35
EXECUTE sp_executesql
#SQLString,
#ParmDefinition,
#level = #IntVariable,
#LastlnameOUT=#Lastlname OUTPUT
SELECT #output = #Lastlname
select #output