Insert vs Update - sql-server

I have a table where all the fields are declared as nvarchar. If I do an insert into the table all unicode characters come into the fields fine. But when I do an update I am losing some of the characters. Here is my udpate statement:
UPDATE TableII
SET LOCATION = CAST(( COALESCE([CITY], N'') + NCHAR(13) + NCHAR(10)
+ COALESCE([INSTALLATION], N'') + NCHAR(13)
+ NCHAR(10) + LEFT(LOCATION.LATLONG, 2) + N'°'
+ SUBSTRING(LOCATION.LATLONG, 3, 2) + N''''
+ SUBSTRING(LOCATION.LATLONG, 5, 2) + NCHAR(34)
+ N' ' + SUBSTRING(LOCATION.LATLONG, 7, 1)
+ N' ' + SUBSTRING(LOCATION.LATLONG, 8, 3)
+ N'°' + SUBSTRING(LOCATION.LATLONG, 11, 2)
+ N'''' + SUBSTRING(LOCATION.LATLONG, 13, 2)
+ NCHAR(34) + N' ' + SUBSTRING(LOCATION.LATLONG,
15, 1) ) AS NVARCHAR(MAX))
FROM TABLEII
INNER JOIN LOC ON TABLEII.REC = LOC.REC
INNER JOIN LOCATION ON LOC.LOCRECNUM = LOCATION.LOCRECNUM
WHERE ( LOC.LOCSEQ = '1' )
As you can see I have tried a variety of things to force the unicode characters to not be lost, but it does not work.
Any ideas why the insert works fine but this update does not?

Is the City column NVARCHAR? If not, the COALESCE will take that column as it's data type and use it, regardless of what you do with the rest of the code.

Related

Mapping columns without knowing what's in the table

I have an odd situation where I will have data coming from various sources (all flat files, none of which are in my control, and no matter how many times I ask for a standard format, I get different column headers and different column orders). We do not have the manpower to manually go through these files to determine which columns are important. Each flat file will have between two and six "identification" columns. However, some of the columns, individually, are not unique, but their combinations can form unique keys. All told, each flat file can have somewhere around one hundred columns.
So, initially, I planned to load the data into a temp table and ask the user to identify which columns contained which data. Once I know that, I can process the file without issue. I would have the two to six columns to identify matches with existing records and the additional data that I am supposed to gather (all identified by the user).
I was then asked to add in the ability for the system to "recommend" which data columns are which. For that, my plan was a count. I would count how many nonempty values each column has and then count how many of those nonempty values match each of the six possible columns. From there, I can take a simple ratio to determine the likelihood that the data contained is of that particular type. There would be some overvaluing of columns that are not unique, but in general, it is working nicely. The problem is that it is very slow.
I created a metadata table that I am calling UploadedTableColumn which contains every column header of the source file and which column it maps to in the database. Here is my stored procedure to update the counts:
CREATE PROCEDURE stored_Procedure
#FileLoadID INT
AS
BEGIN
DECLARE #SqlCommand NVARCHAR(MAX)
DECLARE the_cursor CURSOR FAST_FORWARD FOR
SELECT N'UPDATE UploadedTableColumn SET NumberNonemptyRows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberID1Rows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N','''') IN (SELECT ID1 FROM ID1Table) AND ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberID2Rows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N','''') IN (SELECT ID2 FROM ID2Table) AND ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberIDDateRows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE IIF(ISDATE(' + DestinationColumnName + N')=1,IIF(CAST(' + DestinationColumnName + N' AS DATE) IN (SELECT IDDate FROM IDDateTable),1,0),0) = 1 AND ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberID4Rows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N', '''') IN (SELECT ID4 FROM ID4Table) AND ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberID5Rows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N', '''') IN (SELECT ID5 FROM ID5Table) AND ISNULL(' + DestinationColumnName + N','''') <> ''''),' + CHAR(13)
+ N'NumberID6Rows = (SELECT COUNT(*) FROM ' + DestinationTableName + N' WHERE ISNULL(' + DestinationColumnName + N', '''') IN (SELECT ID6 FROM ID6Table) AND ISNULL(' + DestinationColumnName + N','''') <> '''')' + CHAR(13)
+ N'WHERE DestinationTableName = ''' + DestinationTableName + N''' AND DestinationColumnName = ''' + DestinationColumnName + N''' AND FileLoadID = ' + CAST(#FileLoadID AS NVARCHAR) + N';' + CHAR(13) As SqlCommand
FROM UploadedTableColumn
WHERE FileLoadID = #FileLoadID
OPEN the_cursor
FETCH NEXT FROM the_cursor
INTO #SqlCommand
WHILE ##FETCH_STATUS = 0
BEGIN
EXECUTE(#SqlCommand)
FETCH NEXT FROM the_cursor
INTO #SqlCommand
END
CLOSE the_cursor
DEALLOCATE the_cursor
END
Is there a faster approach?
One small change that might help.
You say you're holding every column of the source table in UploadedTableColumn - you don't need to do that, your cursor is looping through a lot of unnecessary columns. You can eliminate a lot with a pre-emptive column name match.
So get a combined list of all possible ID columns from your ID1Table, ID2Table, etc, and only pull into UploadedTableColumn the ones that actually match a column in DestinationTableName.
On the basis that there are probably no more than 6 columns in your source data that have a matching ID column name, you're now only checking those rather than all 100+.
Of course, this doesn't help you if you've got people sending data without headers and no agreed format.
Pseudo code to get the desired columns:
SELECT name
FROM sys.columns
WHERE [object_id] = OBJECT_ID('DestinationTableName')
AND Name IN
(
SELECT ID1 AS IDColumn FROM ID1Table
UNION ALL
SELECT ID2 AS IDColumn FROM ID2Table
...
)

SQL dynamic query check for null, or empty string parameter

I am writing a stored procedure that will be executed from an SSRS report. It receives 2 parameters: SourceID, and ConfirmationNumber but it is not working for all the tests that I am running
this returns recs:[dbo].[GetParkingPaymentInformation] 'PARC', ''
this does not return recs:[dbo].[GetParkingtPaymentInformation] 'PARC', NULL
this does not return recs:[dbo].[GetParkingPaymentInformation] '', '002077770'
this does not return recs:[dbo].[GetParkingPaymentInformation] NULL, '002077770'
this does return recs:[dbo].[GetParkingPaymentInformation] 'PARC', '002077770'
I want the sp to work when one or the other parameter are either null, or blank.
This is what I have so far for code:
SET #s_SQL = 'SELECT d.ID, d.TransactionNumber, h.SourceType, ' + #s_ColumnName + ', d.FirstName, d.LastName,' +
'LTRIM(RTRIM(d.FirstName)) + '' '' + LTRIM(RTRIM(d.LastName)) [Name], '+
'd.PaymentAmount, CONVERT(VARCHAR(10), CAST(d.InitiationDate AS DATE), 101) [InitiationDate]' +
', d.Fee, d.TotalAmount, d.PaymentStatus, d.PaymentType, d.CreditCardType, ' +
'CONVERT(VARCHAR(10), CAST(d.PaymentEffectiveDate AS DATE), 101) [PaymentEffectiveDate]' +
', CONVERT(VARCHAR(10), CAST(d.ProcessDate AS DATE), 101) [ProcessDate], CONVERT(VARCHAR(10), CAST(d.CreatedDate AS DATE), 101) [CreatedDate],' +
'd.CashCode, d.TransConfirmID' +
', d.Phone, d.StreetAddress1, d.StreetAddress2, ' +
'LTRIM(RTRIM(d.StreetAddress1)) + '' '' + CASE WHEN LEN(d.StreetAddress2) > 0 THEN LTRIM(RTRIM(d.StreetAddress2)) ELSE '''' END [Address]' +
', d.City, d.[State], d.ZipFive, d.ZipFour, d.Email ' +
'FROM '+ #s_TableHeader + ' h WITH (NOLOCK) ' +
'INNER JOIN ' + #s_TableDetail + ' d WITH (NOLOCK) ' +
'ON h.ID = d.headerID ' +
'WHERE' +
' ((h.sourcetype = ' + '''' + #s_Source_Type + '''' + ') OR ' + '''' + #s_Source_Type + '''' + ' IS NULL OR ' + '''' + #s_Source_Type + '''' + '= '''')' +
' AND ((d.transconfirmid = ' + '''' + #s_Confirmation_Number + '''' + ') OR ' + '''' + #s_Confirmation_Number + '''' + ' IS NULL OR ' + '''' + #s_Confirmation_Number + '''' + '= '''')'
Any help I can get to figure why my checks are not working, it would be great.
*Please note that your example sql code is incomplete and that you name the parameters slightly different from the variables which makes for difficulty understanding the question. *
It is not without reason that the use of dynamic sql is discouraged even in cases where the dangers of sql injection are negligible. One of the primary reasons for this is that dynamic sql is difficult to write, read and debug. That being said I have often found myself using it to solve for problems within poorly designed systems.
I assume that you have investigated alternatives appropriately.
To reduce the complexity of dynamic sql statements I have found that constructing the statement in a modular way to be a good strategy.
In your particular case the use of an 'if' statement (or some variation) may help reduce the complexity of your dynamic where clause and likely help resolve your problem.
Example:
`
set #sql = 'select....... your select statement..... where'
if (#a_Source_Type is not null and len(#a_Source_Type) > 0)
begin
set #sql += '''' + #a_Source_Type + ''' = some_field and '
end
else
begin
set #sql += ' len(isnull(some_field, '''')) = 0 and '
end
set #sql += ' 1 = 1 '
`
The above attempts to move the comparison operators out of the dynamic sql.
I suggest refactoring your query to use a strategy similar to this example as you may find it easier to identify erroneous code.
the final line of the example has proven useful in circumstances where the resulting dynamic sql statement may or may not have where clauses to append
Try changing your WHERE to something like this:
'where' +
' h.sourcetype = ' + isnull(quotename(nullif(#s_Source_Type, ''), ''''), 'h.sourcetype') +
' AND d.transconfirmid = ' + isnull(quotename(nullif(#s_Confirmation_Number, ''), ''''), 'd.transconfirmid')

SQL Server 2008 - WHILE Loop

I have a problem that I can not solve, my final goal is to make a trigger that runs every time it is inserted in the 'factura' table and then fill an intermediate table that only has one field (varchar max), because ?, because I have a component in Java that reads this field and generates a file.txt that he later used, but I have a problem that I can not solve, I was seeing what could be with a cursor or better still with a while loop but I am entangled, the BD manager that I use is SQL Server 2008, the select query that I use to generate the data that will be filled in the intermediate table in the trigger, consists of two parts, the header and the details, which I seek to do is that it only shows one row per header, but since there are more than 1 detail in some cases it shows repeated rows.
This is my query:
select
--HEADER(CB),
'CB' + '|' + CONVERT(varchar(10),(CONVERT(DATE, f.FECHA))) + '|' +
'20601140897' + '|' + '03' + '|' +
SUBSTRING(f.SERIE, 1, 2) + '0' + SUBSTRING(f.SERIE, 3, 2) + '-' +
REPLACE(STR(f.NUMERO, 8), SPACE(1), '0') + '|' +
CASE
WHEN f.CODIGO = '' THEN '99999999'
ELSE f.CODIGO
END + '|' + '0' + '|' +
CASE
WHEN f.NOMBRE ='' THEN 'Clientes varios'
ELSE f.NOMBRE
END + '|PEN|' +
CONVERT(varchar(13), (CAST(f.SUBTOTAL AS decimal(10, 2)))) +
'|0.00|0.00|' +
CONVERT(varchar(13), (CAST(f.IMPUESTO AS decimal(10, 2)))) +
'|0.00|0.00|0.00|0.00|' +
CONVERT(varchar(13), (cast(f.TOTAL as decimal(10, 2)))) + '|0.00|0.00|' +
'MONTO TOTAL' + '|||||||1000||||0.00|0.00|0.00||' + CHAR(13) + CHAR(10) +
--DETAIL(DF)
'DB' + '|' + 'NUMBER OF ROW' + '|' + d.PRODUCTO + '|' + 'NIU' + '|' + '1' + '|' +
d.DESCRIPCIO + '|' + CONVERT(varchar(13),(ROUND((d.PRECIO/1.18), 2))) + '|' +
CONVERT(varchar(13), (cast(d.PRECIO as decimal(10, 2)))) + '|' +
CONVERT(varchar(13), (ROUND(((d.PRECIO/1.18) * 0.18), 2))) + '|10|0.00||' +
CONVERT(varchar(13), (cast(d.TOTAL as decimal(10, 2)))) + '|0.00||0.00||'
FROM
factura f
FULL JOIN
detalle d ON f.NUMERO = d.NUMERO
FULL JOIN
clientes c ON f.CODIGO = c.codigo
And this is what it shows:
CB|2017-10-08|20601140897|03|B001-00002224|000700323|0|Clientes
varios|PEN|25.42|0.00|0.00|4.58|0.00|0.00|0.00|0.00|30.00|0.00|0.00|MONTO
TOTAL|||||||1000||||0.00|0.00|0.00|| DB|NUMBER OF
ROW|220|NIU|1|TODO EL
DIA|8.47|10.00|1.53|10|0.00||10.00|0.00||0.00||
CB|2017-10-08|20601140897|03|B001-00002224|000700323|0|Clientes
varios|PEN|25.42|0.00|0.00|4.58|0.00|0.00|0.00|0.00|30.00|0.00|0.00|MONTO
TOTAL|||||||1000||||0.00|0.00|0.00|| DB|NUMBER OF
ROW|230|NIU|1|10 MIN FIN DE
SEMANA|16.94|20.00|3.06|10|0.00||20.00|0.00||0.00||
What I look for:
CB|2017-10-08|20601140897|03|B001-00002224|000700323|0|Clientes
varios|PEN|25.42|0.00|0.00|4.58|0.00|0.00|0.00|0.00|30.00|0.00|0.00|MONTO
TOTAL|||||||1000||||0.00|0.00|0.00|| DB|NUMBER OF
ROW|220|NIU|1|TODO EL
DIA|8.47|10.00|1.53|10|0.00||10.00|0.00||0.00|| DB|NUMBER OF
ROW|230|NIU|1|10 MIN FIN DE
SEMANA|16.94|0.00|3.06|10|0.00||20.00|0.00||0.00||
Somebody could help me? or give me a structure to be able to achieve it, please, I'd be really grateful.
Here is the query, which will append the detail data when there is an identical header data. Query is slow as it involves JOIN on string and large column, You can replace CTE with temp table and by adding index may give a better performance.
;WITH CTE AS (
select
--HEADER(CB),
'CB' + '|' + CONVERT(varchar(10),(CONVERT(DATE, f.FECHA))) + '|' +
'20601140897' + '|' + '03' + '|' +
SUBSTRING(f.SERIE, 1, 2) + '0' + SUBSTRING(f.SERIE, 3, 2) + '-' +
REPLACE(STR(f.NUMERO, 8), SPACE(1), '0') + '|' +
CASE
WHEN f.CODIGO = '' THEN '99999999'
ELSE f.CODIGO
END + '|' + '0' + '|' +
CASE
WHEN f.NOMBRE ='' THEN 'Clientes varios'
ELSE f.NOMBRE
END + '|PEN|' +
CONVERT(varchar(13), (CAST(f.SUBTOTAL AS decimal(10, 2)))) +
'|0.00|0.00|' +
CONVERT(varchar(13), (CAST(f.IMPUESTO AS decimal(10, 2)))) +
'|0.00|0.00|0.00|0.00|' +
CONVERT(varchar(13), (cast(f.TOTAL as decimal(10, 2)))) + '|0.00|0.00|' +
'MONTO TOTAL' + '|||||||1000||||0.00|0.00|0.00||' + CHAR(13) + CHAR(10) HeaderData,
--DETAIL(DF)
'DB' + '|' + 'NUMBER OF ROW' + '|' + d.PRODUCTO + '|' + 'NIU' + '|' + '1' + '|' +
d.DESCRIPCIO + '|' + CONVERT(varchar(13),(ROUND((d.PRECIO/1.18), 2))) + '|' +
CONVERT(varchar(13), (cast(d.PRECIO as decimal(10, 2)))) + '|' +
CONVERT(varchar(13), (ROUND(((d.PRECIO/1.18) * 0.18), 2))) + '|10|0.00||' +
CONVERT(varchar(13), (cast(d.TOTAL as decimal(10, 2)))) + '|0.00||0.00||' DetailData
FROM factura f FULL JOIN detalle d ON f.NUMERO = d.NUMERO
FULL JOIN clientes c ON f.CODIGO = c.codigo
)
select HeaderData+STUFF((SELECT '|'+ DetailData
FROM CTE C
WHERE C.HeaderData=T.HeaderData
FOR XML PATH('')),1,1,'')
FROM CTE T
GROUP BY HeaderData

Stored Procedure - Error converting data type varchar to float

I am trying to insert a float value from one table into another, but am getting the error in the subject line of this post:
Error converting data type varchar to float.
Both fields in both tables are set to float. Values are latitudes and longitudes for zip codes. An example of a latitude/longitude would be:
45.895698
-72.365896
Here is a few snippets of my code:
declare #v_latitude float
declare #v_longitude float
-- Grab Latitude & Longitude --
if #v_zip_code IS NOT NULL
SELECT #v_latitude=z_latitude, #v_longitude=z_longitude FROM tbl_ZipCodes WHERE z_zip_code = #v_zip_code
set #strValues = #strValues + '''' + #v_city + ''', ''' + #v_state + ''', ''' + #v_zip_code + ''', ''' + #v_daytime_phone + ''', ''' + #v_contact_name + ''', '''
+ #v_email_address + ''', ' + cast(#u_id as varchar) + ', ' + cast(#d_id as varchar) + ', 1, ''' + cast(CURRENT_TIMESTAMP as varchar) + ''', 1 , ''' + cast(#v_latitude as float) + ''', ''' + cast(#v_longitude as float) + ''', '''
+ cast(CURRENT_TIMESTAMP as varchar) + ''', dft.df_t_id, (SELECT CASE WHEN dft.df_t_v_price <> 0 THEN dft.df_t_v_price WHEN dft.df_t_v_internet_price <> 0 THEN dft.df_t_v_internet_price WHEN dft.df_t_v_other_price <> 0 THEN dft.df_t_v_other_price ELSE 0 END AS v_search_price)'
The part of the code that uses the #v_latitude and #v_longitude variables is here:
... , ''' + cast(#v_latitude as float) + ''', ''' + cast(#v_longitude as float) + ''', ...
Ignore the "..." as I am demonstrating there is additional code that surrounds those values.
Any help would be appreciated!
Edit: Here is additional code I am using:
-- Check For User Profile --
SELECT #counter = COUNT(*) FROM tbl_Customers WHERE u_id = #u_id
if #counter > 0
SELECT #v_city=c_city, #v_state =c_state, #v_zip_code=c_zip_code,#v_daytime_phone =c_phone_number FROM tbl_Customers WHERE u_id = #u_id
else
SELECT #v_city=d_city, #v_state =d_state, #v_zip_code=d_zip_code,#v_daytime_phone =d_phone_number FROM tbl_Dealers WHERE d_id = #d_id
-- Grab Contact Information --
SELECT #v_contact_name = u_name, #v_email_address = u_email_address FROM tbl_Users WHERE u_id = #u_id
-- Grab Latitude & Longitude --
if #v_zip_code IS NOT NULL
SELECT #v_latitude=z_latitude, #v_longitude=z_longitude FROM tbl_ZipCodes WHERE z_zip_code = #v_zip_code
-- Add Additional Fields --
set #strFields = #strFields + 'v_city, v_state, v_zip_code, v_daytime_phone, v_contact_name, v_email_address, u_id, d_id, v_processed, v_processed_date, v_active, ,v_latitude, v_longitude, v_last_activity, v_dealerfeed, v_search_price'
set #strJoin = #strJoin + ' LEFT JOIN tbl_Vehicles v ON v.v_stock_number = dft.df_t_v_stock_number'
set #strValues = #strValues + '''' + #v_city + ''', ''' + #v_state + ''', ''' + #v_zip_code + ''', ''' + #v_daytime_phone + ''', ''' + #v_contact_name + ''', '''
+ #v_email_address + ''', ' + cast(#u_id as varchar) + ', ' + cast(#d_id as varchar) + ', 1, ''' + cast(CURRENT_TIMESTAMP as varchar) + ''', 1 , ''' + #v_latitude + ''', ''' + #v_longitude + ''', '''
+ cast(CURRENT_TIMESTAMP as varchar) + ''', dft.df_t_id, (SELECT CASE WHEN dft.df_t_v_price <> 0 THEN dft.df_t_v_price WHEN dft.df_t_v_internet_price <> 0 THEN dft.df_t_v_internet_price WHEN dft.df_t_v_other_price <> 0 THEN dft.df_t_v_other_price ELSE 0 END AS v_search_price)'
-- Insert Records Into Vehicle Table (but not twice!) --
set #strSQL = 'INSERT INTO tbl_Vehicles (' + #strFields + ') SELECT ' + #strValues + ' FROM tbl_DealerFeed_temp dft ' + #strJoin + ' WHERE dft.df_t_processed = 0 AND dft.df_d_id = ' + cast(#df_d_id as varchar)
set #strSQL = #strSQL + ' AND dft.df_t_v_stock_number NOT IN ( SELECT v.v_stock_number FROM tbl_Vehicles v WHERE v.d_id = ' + cast(#d_id as varchar) + ')'
print #strSQL
EXEC (#strSQL)
The problem probably is the fact that your dynamic sql is putting single quotes around the float.
Try changing
, ''' + cast(#v_latitude as float) + ''', ''' + cast(#v_longitude as float) + ''', ..
into
, ' + STR(#v_latitude,<length>,<decimals>) + ', ' + STR(#v_longitude,<length>,<decimals>) + ', ..
See STR () for reference
As you're doing dynamic SQL you force everything down to a string type.
But it's the single quotes that are tripping you up. If the column you're inserting into is a float you don't want your float value on the insert wrapped in quotes.
Also I find CONVERT is a little more flexible (with dates mostly) than CAST (I've only done CONVERT for diversity):
so you want get rid of those triple quotes:
...+ CONVERT(varchar(20), #v_latitude) +',' + CONVERT(varchar(20), #v_longitude) +...
Edited to add: your fixed code should look like this:
set #strValues = #strValues + '''' + #v_city + ''', ''' + #v_state + ''', ''' + #v_zip_code + ''', ''' + #v_daytime_phone + ''', ''' + #v_contact_name + ''', '''
+ #v_email_address + ''', ' + cast(#u_id as varchar) + ', ' + cast(#d_id as varchar) + ', 1, ''' + cast(CURRENT_TIMESTAMP as varchar) + ''', 1 , ' + Convert(varchar(20), #v_latitude) + ', ' + Convert(varchar(20), #v_longitude) + ', '''
+ cast(CURRENT_TIMESTAMP as varchar) + ''', dft.df_t_id, (SELECT CASE WHEN dft.df_t_v_price <> 0 THEN dft.df_t_v_price WHEN dft.df_t_v_internet_price <> 0 THEN dft.df_t_v_internet_price WHEN dft.df_t_v_other_price <> 0 THEN dft.df_t_v_other_price ELSE 0 END AS v_search_price)'
Execute your SQL without the EXEC (#strSQL) and have a look at the printed SQL
Edited again; to fix your Float being limited to being rounded to 4 decimal places (this is down to it being a Float) but you can get around it by converting it to a decimal first or using STR, this'll help you understand what's happening:
declare #v_latitude float = -45.12345678
print #v_latitude
print 'Cast = '+ cast( #v_latitude as varchar)
print 'Convert = '+ convert(varchar(20), #v_latitude)
print 'Cast via decimal = '+ cast( cast(#v_latitude as decimal(18,9)) as varchar)
print 'Convert via decimal = '+ convert( varchar(20), convert(decimal(18,9), #v_latitude))
print 'str = '+ str(#v_latitude,18,9)
==
-45.1235
Cast = -45.1235
Convert = -45.1235
Cast via decimal = -45.123456780
Convert via decimal = -45.123456780
str = -45.123456780
you can try
''' + cast( #v_latitude as varchar(20))
+ ''', ''' + cast((#v_longitude as varchar(20))+ '''

Stored Procedure with a conditional?

I trying to rewrite a stored procedure and my SQL is not very good. What i'm hoping to do is write it so that if ModuleID is 555 then select a custom date range (eg. 2012-01-01 2012-12-31). The Current SP is below.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
/*** EventsGetByRange ***/
ALTER PROCEDURE [dbo].[EventsGetByRange]
(
#Filter nvarchar(500),
#BeginDate datetime,
#EndDate datetime
)
AS
SET DATEFORMAT mdy
Declare #sql nvarchar(4000)
Select #sql = 'SELECT E.PortalID, E.EventID, E.RecurMasterID, E.ModuleID, E.EventDateBegin, E.EventDateEnd, '
+ 'E.EventTimeBegin, E.Duration, E.EventName, E.EventDesc, '
+ 'E.Importance, E.CreatedDate, '
+ 'CreatedBy = U.DisplayName, '
+ 'CreatorID = E.CreatedBy, '
+ 'E.Every, '
+ 'E.Period, '
+ 'E.RepeatType, '
+ 'E.Notify, '
+ 'E.approved, '
+ 'E.Signups, '
+ 'E.MaxEnrollment, '
+ '(Select count(*) from dbo.EventsSignups WHERE EventID = E.EventID and E.Signups = 1) as Enrolled, '
+ 'E.EnrollRoleID, '
+ 'E.EnrollFee, '
+ 'E.EnrollType, '
+ 'E.PayPalAccount, '
+ 'E.PayPalPassword, '
+ 'E.Cancelled, '
+ 'E.DetailPage, '
+ 'E.DetailNewWin, '
+ 'E.DetailURL, '
+ 'E.ImageURL, '
+ 'E.ImageType, '
+ 'E.ImageWidth, '
+ 'E.ImageHeight, '
+ 'E.ImageDisplay, '
+ 'E.Location, '
+ 'c.LocationName, '
+ 'c.MapURL, '
+ 'E.Category, '
+ 'b.CategoryName, '
+ 'b.Color, '
+ 'b.FontColor, '
+ 'E.Reminder, '
+ 'E.TimezoneOffset, '
+ 'E.SendReminder, '
+ 'E.ReminderTime, '
+ 'E.ReminderTimeMeasurement, '
+ 'E.ReminderFrom, '
+ 'E.SearchSubmitted, '
+ 'E.CustomField1, '
+ 'E.CustomField2, '
+ 'E.EnrollListView, '
+ 'E.DisplayEndDate, '
+ 'E.AllDayEvent, '
+ 'E.OwnerID, '
+ 'OwnerName = O.DisplayName, '
+ 'E.LastUpdatedAt, '
+ 'LastUpdatedBy = L.DisplayName, '
+ 'E.LastUpdatedID, '
+ '(Select ModuleTitle from dbo.Modules WHERE ModuleID = E.ModuleID) as ModuleTitle, '
+ 'RMOwnerID = r.OwnerID, '
+ 'r.RRULE, '
+ 'E.OriginalDateBegin, '
+ 'E.NewEventEmailSent '
+ 'FROM dbo.Events E '
+ 'inner join dbo.EventsRecurMaster AS r on E.RecurMasterID = r.RecurMasterID '
+ 'left outer join dbo.Users U on E.CreatedBy = U.UserID '
+ 'left outer join dbo.Users O on E.OwnerID = O.UserID '
+ 'left outer join dbo.Users L on E.LastUpdatedID = L.UserID '
+ 'left join dbo.EventsCategory b on E.Category = b.Category '
+ 'left join dbo.EventsLocation c on E.Location = c.Location '
+ 'WHERE (E.ModuleID = 555 AND E.EventTimeBegin BETWEEN 2012-01-01 AND 2012-12-31) OR ((E.EventTimeBegin <= DATEADD(DAY,1,''' + convert(varchar, #EndDate) + ''') AND DATEADD(minute,E.Duration,E.EventTimeBegin) >= ''' + convert(varchar, #BeginDate) + ''') OR '
+ ' (E.EventTimeBegin BETWEEN ''' + convert(varchar, #BeginDate) + ''' AND DATEADD(DAY,1,''' + convert(varchar, #EndDate) + ''')))'
+ ' AND E.Approved = 1'
+ ' AND E.Cancelled = 0'
+ ' ' + #Filter + ' '
+ ' ORDER BY E.EventDateBegin, E.EventTimeBegin, E.EventDateEnd'
EXEC (#sql)
UPDATE: I used the where statemnnt that Diego recommended but that is not having the desired result. It does not act as and If\Else scanrio (which makes sense when I think about it).
I need to first identify if the module ID is 555 and if so only pull the dates from in the hard coded range otherwise execute it as written. Please let me know if more detail is required.
is the proc failing?
did you try adding E.ModuleID = 555 on the where clause?
Do you really want to hard code the value 555? how about passing it
on a parameter?
And most important question: why adding the sql statement to a
variable and execute it? why not just run the SQL? Is it because of
the #Filter variable?
also, sql server 2005 or 2008?
why nvarchar and not varchar on your variables ("n" occupies double
of space)
EDIT:
ok, you have a OR in there so it may be tricky. Do you want everything from code 555 despite the date range value, or everything within the date range and code 555?
I assume option 2 would make more sense so just add
E.ModuleID = 555
before the
+ ' AND E.Approved = 1'

Resources