sp_executesql bug? - sql

Why I get error when call my stored procedure using sp_executesql?
Doesn't works.
exec sp_executesql N'sp_clnt_regional_experts_territories',
N'#action nvarchar(3), #regional_expert_id int,#region_id int,#territory_id int',
#action = N'SEL',
#regional_expert_id = 2,
#region_id = -1,
#territory_id = -1
Procedure or function 'sp_clnt_regional_experts_territories' expects
parameter '#action', which was not supplied.
Works fine:
EXEC sp_clnt_regional_experts_territories
#action = N'SEL',
#regional_expert_id = 2,
#region_id = -1,
#territory_id = -1
Where the stored proc is:
ALTER PROCEDURE [dbo].[sp_clnt_regional_experts_territories]
#action NVARCHAR(3),
#regional_expert_id INT = -1,
#region_id INT = -1,
#territory_id INT = -1

Your sp_executesql is wrong .You need to format it like the one below
DECLARE #SQLString NVARCHAR(500)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #action nvarchar(3)
DECLARE #regional_expert_id int
DECLARE #region_id int
DECLARE #territory_id INT
Set #SQLString=N'EXEC sp_clnt_regional_experts_territories #action,
#regional_expert_id ,#region_id ,#territory_id'
Set #ParmDefinition='#action NVARCHAR(3),
#regional_expert_id INT ,
#region_id INT ,
#territory_id INT '
EXECUTE sp_executesql
#SQLString,
#ParmDefinition,
#action=N'SEL',
#regional_expert_id=2,
#region_id=-1,
#territory_id=-1
Instead of directly entering everything in one statement ,dissecting your code into different parts helps you find your problems easily .

the error is because you didn't include the parameters right after your stored procedure name, which is required by sp_executesql
exec sp_executesql N'sp_clnt_regional_experts_territories #action,#regional_expert_id ,#region_id ,#territory_id',
N'#action nvarchar(3), #regional_expert_id int,#region_id int,#territory_id int',
#action = N'SEL',
#regional_expert_id = 2,
#region_id = -1,
#territory_id = -1

sp_executesql says of #params:
Is one string that contains the definitions of all parameters that have been embedded in #stmt.
(Emphasis added)
So, any parameters you identify there must also be mentioned in #stmt, as the other answers have pointed out.

Related

SQL For Json path - auto inserted '\' if parameter content '/'

Declare #ContractCode nvarchar(100) = N'02/HĐLĐ-NGG';
Declare #DateStartWork date = '2020-06-01';
Declare #DeptID int = 2;
Declare #PositionID int = 4;
Declare #HRDecisionID int = 614
Select #ContractCode as ContractCode,
#DateStartWork as DateStartWork,
#DeptID as DeptID,
#HRDecisionID as HRDecisionID
For Json Path
Then the Result =
[{"ContractCode":"02\/HĐLĐ-NGG","DateStartWork":"2020-06-01","DeptID":2,"HRDecisionID":614}]
Instead of right value like:
[{"ContractCode":"02/HĐLĐ-NGG","DateStartWork":"2020-06-01","DeptID":2,"HRDecisionID":614}]
So please help me to answer Why it automatically inserted \ before '/' into ContractCode.

SQL stored procedure call failed with index out of range

I am trying to execute a stored procedure in SQL Server from my java code. This stored procedure is used in some other language and it was working fine from long back. Now I need to integrate it in my java app. I have 15 columns in my table. When I tried this in my java code, its throwing
com.microsoft.sqlserver.jdbc.SQLServerException: The index 11 is out of range
I also see "Error: 0, SQLState: S1093"
My stored procedure
ALTER PROCEDURE [dbo].[user_input_sp]
#Username VARCHAR(10)=NULL,
#UserKey VARCHAR(50)=NULL,
#ReqTime DATETIME=null,
#ResTime DATETIME=null,
#Req TEXT=null,
#Res TEXT=null,
#condition TEXT=null,
#ID INT=null,
#Address VARCHAR(8000) = NULL,
#Task VARCHAR(50) = NULL,
#Direction INT=0,
#Seq INT=0,
#RR BIT=0,
#Correction VARCHAR(8) = NULL,
#PendingTrans VARCHAR(50) = NULL,
#ForwardID VARCHAR(50) = NULL,
#Command VARCHAR(50) = NULL
AS
DECLARE #TSqno int
#IF #Direction=0
BEGIN
EXECUTE Basp_NewKey 'web_log', #TSqno OUTPUT
Insert into cbscne dbo WebServiceLog( Order, US_Name, US_Key , US_ReqD, US_ResD, US_Req , US_Res, cond, ID ,Address, Task, Command)
values (#TSqno, #Username, #UserKey, #ReqTime, #ResTime, #Req ,#Res, #condition, #ID ,#Address, #Task ,#Command)
END
.......
My java code
public vold addWebServiceLogRequest(UserInput cd){
sessionFactory = sqlServerEMFactory.unwrap(SessionFactory.class);
Session sessionForSave = sessionFactory.openSession();
sessionForSave.beginTransaction();
sessionForSave.doReturningWork(connection-> {
try(CallableStatement cstmt = connection.prepareCall("{call user_input_sp(?,?,?,?,?,?,?,?,?)}")) {
cstmt.setInt("indicator", 0);
cstmt.setString("Username",cd.getInterfaceName());
cstmt.setInt("User_code",cd.getCaseId());
cstmt.setTimestamp("RetrieveDate",cd.getRequestDate());
cstmt.setTimestamp("ReturnDate",cd.getResponseDate());
cstmt.setString("Req",cd.getRequestxml());
cstmt.setString("Res",cd.getResponsexml());
cstmt.setString("Task",cd.getTask());
cstmt.setString("flow",null);
cstmt.execute();
cstmt.close();
connection.close();
return null;
}
});
}

Why ##rowcount returns 0 when more than 1 user access store procedure for insertion

i am using asp.net, i am calling insertion store procedure whihc works fine until one person is inserting but throw error when more than 1 person simultaneously inserts records i.e. ##RowCount stores 0 and returns 0 to application.
USE [CPOCMS]
GO
/** Object: StoredProcedure [dbo].[InsertComplaints] Script Date: 9/24/2014 11:56:13 AM **/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[InsertComplaints]
#ComplaintCode varchar(50),
#ComplaintType_ID smallint,
#RecievingMode_ID smallint,
#Subject varchar(100),
#ComplainantID smallint,
#District_ID smallint,
#AddressedTo varchar(50),
#DiaryNo varchar(50),
#User_ID int,
#Status_ID smallint,
#RecievedDate smalldatetime,
#IGRemarks varchar(MAX) = null,
#PsoRemarks varchar(MAX) =null,
#FinalDecision varchar(250)=null,
#AgainstDist_ID smallint,
#HomePS_ID smallint,
#AgainstPS_ID smallint,
#Name varchar(75),
#DesigID int,
#ForwardedBy smallint,
#SMS_ID int = 0,
#result bit output,
#ID int output
AS
BEGIN
Begin Try
insert into dbo.Complaints
values (
#ComplaintCode,
#ComplaintType_ID,
#RecievingMode_ID ,
#Subject,
#ComplainantID ,
#District_ID ,
#AddressedTo ,
#DiaryNo,
#User_ID,
#Status_ID,
#RecievedDate,
#IGRemarks,
#PsoRemarks,
#FinalDecision,
#AgainstDist_ID,
#HomePS_ID,
#AgainstPS_ID,
#Name ,
#DesigID,
#ForwardedBy,
#SMS_ID
)
Set #result = ##ROWCOUNT
Select #ID= Ident_Current('dbo.Complaints')
End Try
Begin Catch
Set #result=0
End Catch
END
in sql it shows ##Rowcount = 0 and in asp.net it returns #result=0 , why ?
cmd.ExecuteNonQuery();
Boolean Result = Convert.ToBoolean(pResult.Value);
if (Result)
{
int i = Convert.ToInt32(pID.Value);
return i;
}
else
{
return 0;
}
Note: i have removed unnecessary code.

Cannot insert to more than one table

I am trying to execute a stored procedure via excel VBA, however the stored procedure only inserts a record into a single table and throws an error message when the other 2 records are to be inserted to their respective tables
The error message is thrown on the VBA side however in SQL management studio there are no errors yet it still only inserts to the single table.
--Edit:
Error message I receive VBA side
Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.
USE [MainRoads]
GO
/****** Object: StoredProcedure [mruser].[sp_InsertUpdateProject] Script Date: 18/09/2013 3:04:49 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [mruser].[sp_InsertUpdateProject]
-- Add the parameters for the stored procedure here
--#ProjectRecord_ID numeric(18,0),
#lProjectNumber numeric(18,0),
#sProjectName nvarchar(300),
#sProjectType nvarchar(100),
#sDirectorate nvarchar(300),
#sProjectManager nvarchar(300),
#sContractType nchar(10),
#sProjectDescription nvarchar(max),
#sCurrentPhase nvarchar(50),
#sProjectStartDate date,
#sPlannedCompDate date,
#sReportingPeriod nchar(10),
#sProjectStatusAt date,
#sPSRApprovedBy nvarchar(100),
#sPSRApprovedDate date,
#sProjectOverallHlth text,
#sProjectWrkflwStatus nchar(10),
#sProjectRAGStatus nchar(10),
#sAssessRAG nchar(10),
#sSelectRAG nchar(10),
#sDevelopRAG nchar(10),
#sDeliverRAG nchar(10),
#sOperateRAG nchar(10),
#lTotalOrigBudget decimal(18,2),
#lTotalAppBudget decimal(18,2),
#lActualsLifeToDate decimal(18,2),
#lTotalForecastToComplete decimal(18,2),
#lTotalProjVar decimal(18,2),
#lCommFunding decimal(18,2),
#lStateFunding decimal(18,2),
#lOthFunding decimal(18,2),
#sCommFundType nvarchar(50),
#sStateFundType nvarchar(50),
#sOthFundType nvarchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
Declare #v_recordexist int
Select #v_recordexist = count(*) From Project_Information Where Project_Number = #lProjectNumber
--If record does not exists update record
IF #v_recordexist = 0
BEGIN
INSERT INTO [mruser].[Project_Information] ([Project_Number], [Project_Name], [Project_Type], [Directorate], [Project_Manager],[Contract_Type], [Project_Description], [Current_RO&DS_Phase], [Project_Start_Date],[Planned_Completion_Date], [Reporting_Period], [Project_Status_At], [PSR_Approved_By], [PSR_Approved_Date], [Project_Overall_Health], [Project_Workflow_Status], [Project_RAG_Status], [Date_Inserted] )
values(#lProjectNumber, #sProjectName, #sProjectType, #sDirectorate, #sProjectManager, #sContractType, #sProjectDescription, #sCurrentPhase, #sProjectStartDate, #sPlannedCompDate, #sReportingPeriod, #sProjectStatusAt, #sPSRApprovedBy, #sPSRApprovedDate, #sProjectOverallHlth, #sProjectWrkflwStatus, #sProjectRAGStatus, GETDATE())
--SELECT SCOPE_IDENTITY() as ProjectIDNumber
BEGIN
Insert into [mruser].[Project_Finance] ([Project_Number], [Total_Original_Budget], [Total_Approved_Budget], [Actuals_Life_To_Date], [Total_Forecast_Cost_To_Complete], [Total_Project_Variance], [Commonwealth_Funding], [State_Funding], [Other_Funding], [Commonwealth_Fund_Type], [State_Fund_Type], [Other_Fund_Type]) values (#lProjectNumber, #lTotalOrigBudget, #lTotalAppBudget, #lActualsLifeToDate, #lTotalForecastToComplete ,#lTotalProjVar ,#lCommFunding ,#lStateFunding ,#lOthFunding ,#sCommFundType ,#sStateFundType ,#sOthFundType)
--(strClientID, timeReg, timeValid, bCurrent, durum) VALUES (#strClientID,getdate(),getdate() + 30,'1','1')
Insert into [mruser].[Project_Milestones] ([Project_Number], [Assess_RAG_Status], [Select_RAG_Status], [Develop_RAG_Status], [Deliver_RAG_Status], [Operate_RAG_Status]) values(#lProjectNumber, #sAssessRAG, #sSelectRAG, #sDeliverRAG, #sDevelopRAG, #sOperateRAG)
--Insert into [mruser].[Project_Finance] ([Project_Number], [Total_Original_Budget], [Total_Approved_Budget], [Actuals_Life_To_Date], [Total_Forecast_Cost_To_Complete], [Total_Project_Variance], [Commonwealth_Funding], [State_Funding], [Other_Funding], [Commonwealth_Fund_Type], [State_Fund_Type], [Other_Fund_Type]) values (#lProjectNumber, #lTotalOrigBudget, #lTotalAppBudget, #lActualsLifeToDate, #lTotalForecastToComplete ,#lTotalProjVar ,#lCommFunding ,#lStateFunding ,#lOthFunding ,#sCommFundType ,#sStateFundType ,#sOthFundType)
END
End
Else
BEGIN
update [mruser].[Project_Information] set
[Project_Number] = #lProjectNumber,
[Project_Name] = #sProjectName,
[Project_Type] = #sProjectType,
[Directorate] = #sDirectorate,
[Project_Manager] = #sProjectManager,
[Contract_Type] = #sContractType,
[Project_Description] = #sProjectDescription,
[Current_RO&DS_Phase] = #sCurrentPhase,
[Project_Start_Date] = #sProjectStartDate,
[Planned_Completion_Date] = #sPlannedCompDate,
[Reporting_Period] = #sReportingPeriod,
[Project_Status_At] = #sProjectStatusAt,
[PSR_Approved_By] = #sPSRApprovedBy,
[PSR_Approved_Date] = #sPSRApprovedDate,
[Project_Overall_Health] = #sProjectOverallHlth,
[Project_Workflow_Status] = #sProjectWrkflwStatus,
[Project_RAG_Status] = #sProjectRAGStatus
where [Project_Number] = #lProjectNumber
update [mruser].[Project_Milestones] set
[Project_Number] = #lProjectNumber,
[Assess_RAG_Status] = #sAssessRAG,
[Select_RAG_Status] = #sSelectRAG,
[Develop_RAG_Status] = #sDeliverRAG,
[Deliver_RAG_Status] = #sDevelopRAG,
[Operate_RAG_Status] = #sOperateRAG
where [Project_Number] = #lProjectNumber
UPDATE [mruser].[Project_Finance] set
[Project_Number] = #lProjectNumber,
[Total_Original_Budget] = #lTotalOrigBudget,
[Total_Approved_Budget] = #lTotalAppBudget,
[Actuals_Life_To_Date] = #lActualsLifeToDate,
[Total_Forecast_Cost_To_Complete] = #lTotalForecastToComplete,
[Total_Project_Variance] = #lTotalProjVar,
[Commonwealth_Funding] = #lCommFunding,
[State_Funding] = #lStateFunding,
[Other_Funding] = #lOthFunding,
[Commonwealth_Fund_Type] = #sCommFundType,
[State_Fund_Type] = #sStateFundType,
[Other_Fund_Type] = #sOthFundType
where [Project_Number] = #lProjectNumber
END
End
Turns out that it was due to not referencing the IDENTITY on the primary table.
I passed SCOPE_IDENTITY() to a variable and now it all works without a hitch.

sp_send_dbmail attach files stored as varbinary in database

I have a two part question relating to sending query results as attachments using sp_send_dbmail.
Problem 1: Only basic .txt files will open. Any other format like .pdf or .jpg are corrupted.
Problem 2: When attempting to send multiple attachments, I receive one file with all file names glued together.
I'm running SQL Server 2005 and I have a table storing uploaded documents:
CREATE TABLE [dbo].[EmailAttachment](
[EmailAttachmentID] [int] IDENTITY(1,1) NOT NULL,
[MassEmailID] [int] NULL, -- foreign key
[FileData] [varbinary](max) NOT NULL,
[FileName] [varchar](100) NOT NULL,
[MimeType] [varchar](100) NOT NULL
I also have a MassEmail table with standard email stuff. Here is the SQL Send Mail script. For brevity, I've excluded declare statements.
while ( (select count(MassEmailID) from MassEmail where status = 20 )>0)
begin
select #MassEmailID = Min(MassEmailID) from MassEmail where status = 20
select #Subject = [Subject] from MassEmail where MassEmailID = #MassEmailID
select #Body = Body from MassEmail where MassEmailID = #MassEmailID
set #query = 'set nocount on; select cast(FileData as varchar(max)) from Mydatabase.dbo.EmailAttachment where MassEmailID = '+ CAST(#MassEmailID as varchar(100))
select #filename = ''
select #filename = COALESCE(#filename+ ',', '') +FileName from EmailAttachment where MassEmailID = #MassEmailID
exec msdb.dbo.sp_send_dbmail
#profile_name = 'MASS_EMAIL',
#recipients = 'me#myemail.com',
#subject = #Subject,
#body =#Body,
#body_format ='HTML',
#query = #query,
#query_attachment_filename = #filename,
#attach_query_result_as_file = 1,
#query_result_separator = '; ',
#query_no_truncate = 1,
#query_result_header = 0;
update MassEmailset status= 30,SendDate = GetDate() where MassEmailID = #MassEmailID
end
I am able to successfully read files from the database so I know the binary data is not corrupted.
.txt files only read when I cast FilaData to varchar. But clearly original headers are lost. It's also worth noting that attachment file sizes are different than the original files. That is most likely due to improper encoding as well. So I'm hoping there's a way to create file headers using the stored mimetype, or some way to include file headers in the binary data?
I'm also not confident in the values of the last few parameters, and I know coalesce is not quite right, because it prepends the first file name with a comma. But good documentation is nearly impossible to find. Please help!
I don't think your going to be able to send binary data directly from SQL. There are a few posts out there that talk about this same issue. From the Microsoft documentation a text return to the query is formatted as a text file. Binary is formatted as a hexadecimal. Which as you have pointed out corrupts any file that isn't a text document.
I think you could still accomplish what you're trying to do however by first using BCP to export the binary data out to the file system, and then importing it back in via traditional file attachment methods made available to sendmail.
So something like this. (concept only - untested code)
DECLARE #OutputFileAndPath VarChar(500) = '\\Log_Files\MyFile.pdf '
DECLARE #sql VarChar(8000)
SELECT #sql = 'BCP "SELECT MyFile FROM [dbo].[MyTable]
WHERE PrimaryKey = 12345" queryout ' + #OutputFileAndPath +
' -S MyServer\MyInstance -T -fC:\Documents.fmt'
/* you could use a generic format file that would cover most formats */
EXEC xp_cmdshell #sql, NO_OUTPUT;
while ( (select count(MassEmailID) from MassEmail where status = 20 )>0)
begin
select #MassEmailID = Min(MassEmailID) from MassEmail where status = 20
select #Subject = [Subject] from MassEmail where MassEmailID = #MassEmailID
select #Body = Body from MassEmail where MassEmailID = #MassEmailID
exec msdb.dbo.sp_send_dbmail
#profile_name = 'MASS_EMAIL',
#recipients = 'me#myemail.com',
#subject = #Subject,
#body =#Body,
#body_format ='HTML',
#file_attachments = #OutputFileAndPath /* i.e. \\Log_Files\MyFile.pdf */
update MassEmailset status= 30,SendDate = GetDate() where MassEmailID = #MassEmailID
end
The sample below will imbed images into the < img > tag, which will work for jpeg, png, and such. It won't solve PDFs, but it does work with images, at least.
declare #eRecipient nvarchar(max) = 'me#example.com';
declare #eSubject nvarchar(max) = 'Testing!';
declare #FileName nvarchar(2000);
declare #MimeType nvarchar(200);
declare #attachText nvarchar(max);
declare #eBody nvarchar(max) = '<html><head><style>table, th, td {border-collapse: collapse;border: 1px solid black;} img {width: 100%; max-width: 640px;}</style></head>' +
'<body><h1>Data with pics!</h1><table>' +
'<tr><th>Some text</th><th>Some Pics</th></tr>';
declare c1 cursor for
select FileName,
MimeType,
/* MimeType should be something like 'image/jpeg' or 'image/png' */
cast('' as xml).value('xs:base64Binary(sql:column("FileData"))', 'varchar(max)') attachText
/* the above uses XML commands to convert the binary attachment to UUencoded text */
from EmailAttachment
order by 1;
open c1;
fetch next from c1 into #FileName, #MimeType, #attachText
while ##FETCH_STATUS = 0
begin
set #eBody = #eBody + '<tr><td>Filename: ' + #FileName +
'</td><td><img src="data:' + #contentType + ';base64,' +
#AttachText + '="></td></tr>';
/* note that the img tag contents the encoded image data, the mime type, and that it ends in an = sign. */
fetch next from c1 into #FileName, #MimeType, #attachText
end;
close c1;
deallocate c1;
set #eBody = #eBody + '</table></body></html>';
exec msdb.dbo.sp_send_dbmail
#recipients = #eRecipient, #body = #eBody, #subject = #eSubject, #body_format='HTML'