Choosing Column name based on variable name to update value - sybase

I have a piece of code to update a column value but it gives me error:
UPDATE #Cal SET #Curr = #2YD where Day = 'D-3WD'
I tried EXEC command using:
SELECT #sql = "UPDATE #Cal SET " + #Cur + " = " + #2YD + "where Day = 'D-2WD'"
EXEC #sql
but I get following error:
Syntax error during implicit conversion of VARCHAR value 'where Day = 'D-2WD'' to a DATE field.
Why is it trying to convert the value to date field?

Try to convert explicitly:
SELECT #sql = "UPDATE #Cal SET " + convert (varchar(25),#Cur) + " = " + convert (varchar(25),#2YD ) + "where Day = 'D-2W

Related

SQL Server : INSTEAD OF UPDATE trigger: dynamic code generation; inserted table not available

I have the following with an INSTEAD OF UPDATE trigger which dynamically generates code and then executes it. The problem is that when the code is executed I always get the error message:
invalid object name 'inserted'
The trigger code is like this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Trigger [dbo].[TACMasterLayouts_VersionVisibilityHandling_updates]
ON [dbo].[TACMasterLayouts_VersionVisibilityHandling]
INSTEAD OF UPDATE
AS
IF ##rowcount = 0
RETURN;
SET NOCOUNT ON
DECLARE #tableToUpdate AS NVARCHAR(MAX) = 'dbo.tacmasterlayouts';
DECLARE #UpdateStatement AS NVARCHAR(MAX)
DECLARE #IdentityField AS NVARCHAR(MAX) = (SELECT Name
FROM sys.columns
WHERE [object_id] = OBJECT_ID('dbo.tacmasterlayouts')
AND is_identity = 1)
SET #UpdateStatement = 'update ' + #tableToUpdate + ' set ';
DECLARE #Fields AS NVARCHAR(MAX)
SELECT #Fields = COALESCE(#Fields + ', ', '') + #tableToUpdate + '.' + Name + ' = inserted.' + Name
FROM sys.columns
WHERE [object_id] = OBJECT_ID('dbo.tacmasterlayouts')
AND Name != #IdentityField;
SET #UpdateStatement = #UpdateStatement + #fields
SET #UpdateStatement = #UpdateStatement + ' FROM ' + #tableToUpdate + ', inserted'
SET #UpdateStatement = #UpdateStatement + ' where ' + #tableToUpdate + '.' + #IdentityField + ' = inserted.' + #IdentityField
EXECUTE sp_executesql #UpdateStatement
The dynamic code looks like this:
UPDATE TACMasterLayouts SET
TACMasterLayouts.TACMasterLayoutName = inserted.TACMasterLayoutName,
TACMasterLayouts.TACMasterLayoutDestinationFileName = inserted.TACMasterLayoutDestinationFileName,
TACMasterLayouts.LayoutTypeCategoryId = inserted.LayoutTypeCategoryId,
TACMasterLayouts.LayoutTypeId = inserted.LayoutTypeId,
TACMasterLayouts.TACMasterLayoutDescription = inserted.TACMasterLayoutDescription,
TACMasterLayouts.TACMasterLayoutJasper = inserted.TACMasterLayoutJasper,
TACMasterLayouts.TACMasterLayoutJrxml = inserted.TACMasterLayoutJrxml,
TACMasterLayouts.TACMasterLayoutHtml = inserted.TACMasterLayoutHtml,
TACMasterLayouts.TACMasterLayoutDontClone = inserted.TACMasterLayoutDontClone,
TACMasterLayouts.TACMasterLayoutIsSubReport = inserted.TACMasterLayoutIsSubReport,
TACMasterLayouts.TACMasterLayoutVersion = inserted.TACMasterLayoutVersion,
TACMasterLayouts.TACMasterLayoutKey = inserted.TACMasterLayoutKey,
TACMasterLayouts.TACMasterLayoutTimestampLastModified = inserted.TACMasterLayoutTimestampLastModified,
TACMasterLayouts.TACMasterLayoutHash = inserted.TACMasterLayoutHash,
TACMasterLayouts.TACMasterLayoutTimestampLastCheckout = inserted.TACMasterLayoutTimestampLastCheckout,
TACMasterLayouts.TACMasterLayoutCheckedOutByUserId = inserted.TACMasterLayoutCheckedOutByUserId,
TACMasterLayouts.TACMasterLayoutIsCheckedIn = inserted.TACMasterLayoutIsCheckedIn,
TACMasterLayouts.TACMasterLayoutCheckedInByUserId = inserted.TACMasterLayoutCheckedInByUserId,
TACMasterLayouts.TACMasterLayoutCheckedOutFolderName = inserted.TACMasterLayoutCheckedOutFolderName
FROM TACMasterLayouts, inserted
WHERE TACMAsterlayouts.TACMasterLayoutId = inserted.TACMasterLayoutId;
Hint:
If I am statically entering the dynamically generated code within the trigger, it works fine. so the code itself is ok.
Question: why is inserted not available in this situation? And how to fix it?
When dynamic sql is executed it has it's own scope like calling another stored procedure, so it can not reference what is in the Trigger's scope like inserted, deleted, or local variables etc. You would have to include a literal value in the dynamic sql string for the required key value and also be prepared to handle more than 1 row in inserted which caused the firing of the trigger.
As the above answers didn't gave me the desired solution, I digged further and found the following - cool - solution (thanks to the following article: https://www.sqlteam.com/forums/topic.asp?TOPIC_ID=11318):
If you need to pass the inserted table into dynamic SQL code (to the sp_executesql stored procedure), do a:
select * from inserted into #inserted
and then you can access it immediately within the sp_executesql under #inserted. No need to pass this as a parameter to the sp_executesql.
the final - working - code looks like this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Trigger [dbo].[TACMasterLayouts_VersionVisibilityHandling_updates] on [dbo].[TACMasterLayouts_VersionVisibilityHandling] INSTEAD OF update
as
if ##rowcount = 0 return;
SET NOCOUNT ON
Declare #tableToUpdate AS Nvarchar(max) = 'dbo.tacmasterlayouts';
Declare #UpdateStatement AS Nvarchar(max)
Declare #IdentityField as Nvarchar(max) = (SELECT Name FROM sys.columns WHERE [object_id] = OBJECT_ID(#tableToUpdate) and is_identity = 1)
set #UpdateStatement = 'update ' + #tableToUpdate + ' set ';
Declare #Fields AS Nvarchar(MAX)
SELECT #Fields = COALESCE(#Fields + ', ', '') + #tableToUpdate + '.' + Name + ' = #inserted.' + Name FROM sys.columns WHERE [object_id] = OBJECT_ID(#tableToUpdate) and Name != #IdentityField;
set #UpdateStatement = #UpdateStatement + #fields
set #UpdateStatement = #UpdateStatement + ' FROM ' + #tableToUpdate + ', #inserted'
set #UpdateStatement = #UpdateStatement + ' where ' + #tableToUpdate + '.' + #IdentityField + ' = #inserted.' + #IdentityField
select * into #inserted from inserted
EXECUTE sp_executesql #UpdateStatement
From what I'm finding, it appears that you likely don't have access to use the inserted table in dynamic SQL in this way, but you should be able to accomplish what you're trying to do using the SQLCLR
Using the inserted / deleted tables in Dynamic SQL

Issue with Dynamic SQL (Also: How to get SQL Lines from ExecuteNonQuery)

I am using Visual Studio, I'm trying to make a Insert statement using C# and Dynamic SQL.
SQL Command:
comando.CommandText = #"
declare #sql nvarchar(max);
set #sql = 'INSERT INTO ' + #curso + '(Data_Local, Deletado) VALUES ( ' + #date + ', 0)';
exec (#sql);
";
#curso is the Table Name, it's working, Data_Local is a Datetime value, which is not working, and Deletado is a bit value, which is working.
Declaring #curso:
comando.Parameters.Add("#curso", SqlDbType.NVarChar);
comando.Parameters["#curso"].Value = idCurso;
Declaring #date
comando.Parameters.Add("#date", SqlDbType.DateTime);
comando.Parameters["#date"].Value = dateTimePicker2.Value.Date;
Then after:
comando.ExecuteNonQuery();
The error message appears:
'Conversion failed when converting date and/or time from character
string.'
What should I do to read the value from the DateTimePicker, insert into the #date variable, and add it to the SQL Command properly?
Also, I have another doubt, where can I see how the SQL Command is sent? I need to see how the lines really are, how is the SQL Command without the variables, with the values instead.
Sorry if my issue is not explained very well, I'll keep trying to make it clear.
Edit:
I tried:
comando.CommandText = #"
declare #sql nvarchar(max);
set #sql = 'INSERT INTO ' + #curso + '(Data_Local, Deletado) VALUES ( ' + #date + ', 0)';
exec (#sql);
";
comando.Parameters.Add("#date", SqlDbType.NVarChar);
comando.Parameters["#date"].Value = "'" + dateTimePicker2.Value.Date + "'";
New error message:
'The conversion of a varchar data type to a datetime data type
resulted in an out-of-range value. The statement has been terminated.'
Edit. Thanks, solved.
Rather use a Stored Procedure, its awful if you going to use dynamic SQL in your c# application. Firstly because as a DBA, Adhoc queries like these are difficult to maintain, and secondly its easier to manage and also easier to apply to code.
1) Create a Stored Procedure
CREATE PROCEDURE Insert_Test
(
#curso VARCHAR(256),
#date VARCHAR(32)
)
AS
SET NOCOUNT ON
DECLARE #sql NVARCHAR(MAX)
IF ISDATE(#date) = 1 --check if its the correct date
BEGIN
SET #sql = 'INSERT INTO ' + #curso + '(Data_Local, Deletado) VALUES ( ''' + #date + ''', 0)'
EXEC (#sql)
END
2) In your c# code
string tbleName = "Test";
DateTime dte = DateTime.Now.ToString();
comando.ExecuteSqlCommand("exec Insert_Test #curso, #date",
new SqlParameter("curso", tbleName),
new SqlParameter("date", dte)
);

Operand type clash: date is incompatible with int with variable in a PRINT statement

I am trying to create a trigger in MS sql server, but I keep receiving a 'Operand type clash: date is incompatible with int' error. I think the error is coming from my PRINT statements but I am not versed enough in sql to know how overcome this problem.
ALTER TRIGGER utrInsteadUpdateTblMembership
ON tblMembership INSTEAD OF UPDATE
AS
BEGIN
DECLARE #newPayDate date, #prevPayDate Date, #prevMemberNumber int
Select #newPayDate = MembershipFeePaidDate FROM inserted
Select #prevPayDate = MembershipFeePaidDate FROM deleted
Select #prevMemberNumber = MembershipID FROM deleted
IF #prevPayDate IS NOT NULL AND #prevPayDate > #newPayDate
BEGIN
UPDATE tblMembership
SET MembershipFeePaidDate = #newPayDate
WHERE #prevMemberNumber = MembershipID
UPDATE tblMembership
SET isCurrentMember = 1
WHERE #prevMemberNumber = MembershipID
PRINT 'Membership Number ' + #prevMemberNumber + ':' + ' payment date is ' + #newPayDate + ';' + ' prior payment date is ' + #prevPayDate
END
ELSE
BEGIN
PRINT 'Membership Number ' + #prevMemberNumber + ':' + ' new payment date ' + #newPayDate + ' is earlier than prior payment date ' + #newPayDate +';' + 'No change made'
END
END
It's cause it interprets it like addition versus concatenation. The same applies for Dynamic SQL
PRINT 'Membership Number ' + cast(#prevMemberNumber as char(8)) + ':' + ' new payment date ' + convert(varchar(10),#newPayDate,101) + ' is earlier than prior payment date ' + convert(varchar(10),#newPayDate,101) +';' + 'No change made'

A single quote in a column breaks the dynamic string

Please help me with a simple formatting of a dynamic string that I'm building so I can run multiple statements at once.
Here is the exact code I have which is breaking when the column value has a single quote and I'm unable to wrap the column text with the proper quotation. I tried using double quotes and quotename function but none worked.
declare #str varchar(max)
set #str = ''
declare #addgo varchar(20)
set #addgo = 'GO'
declare #newline varchar(50)
set #newline = char(13)+char(10)
select #str = coalesce(#str, '') + 'sp_addmessage #msgnum = ' + convert(varchar(50), error) + ' , #severity = 16' + ', #msgtext = N''' + "description" + ''''
+ #newline + #addgo + #newline from [msdb].dbo.sysmessages
where error = '777970005'
print #str
Result:
sp_addmessage #msgnum = 777970005 ,#severity = 16,#msgtext = N'Management group with id '%s' is not a member of this Data Warehouse or you do not have permissions to perform actions for that management group'
GO
Like #KamilG said, use the replace function:
select #str= coalesce(#str,'')+'sp_addmessage #msgnum = '+convert(varchar(50),error)+' ,#severity = 16'+',#msgtext = N'''+replace(description,'''','''''')+''''
+ #newline+#addgo+#newline from [msdb].dbo.sysmessages

Need help in dynamic procedure

I have a start date and end date so how to use both in place of getdate()
I have a code in which if the date interval between start and end date is less than 30 than it should show the start and end date. Instead it is showing error-
Explicit conversion from data type int to date is not allowed.
I am notusing int anywhere but still it is showing I have tried convert in argument passing and other things but its not stopping showing error.
My code is-
if object_id('ias_test_SCHEMA.week2','p') is not null
drop procedure ias_test_SCHEMA.week2;
go
create procedure ias_test_SCHEMA.week2(#startdate date,#enddate date)
as
BEGIN
declare #datediff integer,
#res varchar(30);
set #datediff = DATEDIFF(day, #startdate, #enddate);
if #datediff<=30
begin
declare #stmt nvarchar(max),
#stmt1 nvarchar(max);
set #stmt= N'SELECT #res=(DATENAME(DAY,convert(date,'+convert(nvarchar(20),#startdate)+')) + '' '' + DATENAME(MONTH,convert(date,'+convert(nvarchar(20),#startdate)+')) + '' '' + DATENAME(YEAR,convert(date,'+convert(nvarchar(20),#startdate)+')))';
Execute sp_executesql #stmt, N'#res varchar output',
#res=#res output;
print 'The date is:' + #res;
set #stmt1= N'SELECT DATENAME(DAY,convert(date,'+convert(nvarchar(20),#enddate)+')) + '' '' + DATENAME(MONTH,convert(date,'+convert(nvarchar(20),#enddate)+')) + '' '' + DATENAME(YEAR,convert(date,'+convert(nvarchar(20),#enddate)+'))';
Execute sp_executesql #stmt1;
end;
end;
go
and I am executing it by line-
execute ias_test_SCHEMA.week2 '2015-10-03','2015-10-08';
but it is showing compiled successfully but at the time of result is not showing error. I am stuck here!
Please can anyone help me through it? Thank you!
these are the commands produced by your code:
SELECT #res=(DATENAME(DAY,convert(date,2015-10-03)) + ' ' + DATENAME(MONTH,convert(date,2015-10-03)) + ' ' + DATENAME(YEAR,convert(date,2015-10-03)))
SELECT DATENAME(DAY,convert(date,2015-10-08)) + ' ' + DATENAME(MONTH,convert(date,2015-10-08)) + ' ' + DATENAME(YEAR,convert(date,2015-10-08))
the issue is in the missing quotes around the dates inside the convert built in the dynamic string.
if you run:
select convert(date,2015-10-03);
you get:
Msg 529, Level 16, State 2, Line 1 Explicit conversion from data type
int to date is not allowed.
the following command can be executed successfully:
select convert(date,'2015-10-03');
the solution is to add escaped single quotes when building the dynamic query:
set #stmt= N'SELECT #res=(DATENAME(DAY,convert(date,'''+convert(nvarchar(20),#startdate)+''')) + '' '' + DATENAME(MONTH,convert(date,'''+convert(nvarchar(20),#startdate)+''')) + '' '' + DATENAME(YEAR,convert(date,'''+convert(nvarchar(20),#startdate)+''')))';

Resources