Removing empty list elements from a sql coalesce string - sql-server

I have a query that has this syntax
coalesce(cast([tb_groups].[f_member_id_creator] as varchar) + ',', '') + coalesce(cast([tb_groups].[f_member_id_officer1] as varchar) + ',','') + coalesce(cast([tb_groups].[f_member_id_officer2] as varchar) + ',', '') + coalesce(cast([tb_groups].[f_member_id_officer3] as varchar) + ',','') + coalesce(cast([tb_groups].[f_member_id_officer4] as varchar) + ',', '') + coalesce(cast([tb_groups].[f_member_id_officer5] as varchar),'') as admin_list
F_member_id_creator is always present in the db, however f_member_id_officer1 through 5 may be available in any combination.
For example, a returned value from the above statement might be
"25431,32663,,,,"
or "25431,,32663,,,"
or "25431,,,32663,,"
or "25431,,,,32663,"
etc.
What I need to do is tell SQL to remove the empty list elements and just return "25431,32663"
Any way to do this in SQL Server 2005?
Or better yet, have it not select the empty ordinal at all if its null or blank?

YOU got the result because [tb_groups].[f_member_id_creator], maybe, the empty instead of null. Try this:
coalesce(NULLIF(LTRIM(RTRIM(cast([tb_groups].[f_member_id_creator] as varchar))), '') + ',', '') + ...
If you agree that you haven't trailing and/or leading spaces you can omit LTRIM/RTRIM.

I slightly modified above code... I think it works... because it worked for me
COALESCE(CAST([tb_groups].[f_member_id_creator] as varchar), '') +
COALESCE(NULLIF(',' + CAST([tb_groups].[f_member_id_officer1] as varchar),','), '') +
COALESCE(NULLIF(',' + CAST([tb_groups].[f_member_id_officer2] as varchar),','), '') +
COALESCE(NULLIF(',' + CAST([tb_groups].[f_member_id_officer3] as varchar),','), '') +
COALESCE(NULLIF(',' + CAST([tb_groups].[f_member_id_officer4] as varchar),','), '') +
COALESCE(NULLIF(',' + CAST([tb_groups].[f_member_id_officer5] as varchar),','), '') as admin_list

Related

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')

Dynamic SQL and carriage breaks

I am trying to insert into a table with dynamic sql with the following code:
SET #SQLINSERT = 'INSERT INTO ' + #TABLENAME + ' (OP__DOCID, OP__PARENTID, OP__FOLDERID, CLIENTKEY, ADMISSIONKEY, PGMKEY, ' +
'PGMADMISSIONKEY, STAFFKEY, GroupSize, MealTime, AppMgrKey, SessionNum, FacilityKey, TtmNoteText,' + #DATEFIELD + ', ' + #TIMEFIELD + ') '
SET #SQLVALUES = 'VALUES (' + CAST(#NEWDOCID AS VARCHAR) + ', ' + CAST(#CLIENTKEY AS VARCHAR) + ', ' +
CAST(#CLIENTKEY AS VARCHAR) + ', ' + CAST(#CLIENTKEY AS VARCHAR) + ', ' + CAST(#ADMISSIONKEY AS VARCHAR) + ', ' +
ISNULL(CAST(#PGMKEY AS VARCHAR),'') + ', ' + ISNULL(CAST(#PGMADMISSIONKEY AS VARCHAR),'') + ', ' + CAST(#STAFFKEY AS VARCHAR) + ', ' +
CAST(#GroupSize AS VARCHAR) + ', ' + CAST(#MealTime AS VARCHAR) + ', ' + CAST(#ApprvMgr AS VARCHAR) + ', '
+ CAST(#SessionNum AS VARCHAR) + ', ' + CAST(#FacilityKey AS VARCHAR) + ', ' --Added 10/30/15 JF for FC notes
+ #TtmNoteText +',' --Added 10/30/15 JF for FC notes
+ 'NULL' + ', ' + 'NULL' + ')'
EXEC(#SQLINSERT + #SQLVALUES)
And I want #TtmNoteText to include char(10) and Char(13) like the following
SET #TtmNoteText='Purpose Statement: '+CHAR(13)+CHAR(10) --Added 10/30/15 JF for FC notes
+ 'Family Vision: '+CHAR(13)+CHAR(10)
+ 'Strengths: '+CHAR(13)+CHAR(10)
+ 'Challenges: '+CHAR(13)+CHAR(10)
+ 'Updates: '+CHAR(13)+CHAR(10)
+ 'Progress in Treatment Goals/ITFC Program: '+CHAR(13)+CHAR(10)
+ 'Services/Supports Needed: '+CHAR(13)+CHAR(10)
+ 'Plan:'
I know that I am likely just not using the correct number of single quotes or something like that. Is it possible to insert with line/carriage breaks using dynamic sql
Your entire #SQLVALUES variable is missing a lot of quotes. I'm not sure if this is perfectly accurate, but you need to put single quotes around your string values, but since you're building a dynamic statement, they need to be escaped (escape ' with '):
SET #SQLVALUES = 'VALUES (''' + CAST(#NEWDOCID AS VARCHAR) + ''', ''' + CAST(#CLIENTKEY AS VARCHAR) + ''', ''' +
CAST(#CLIENTKEY AS VARCHAR) + ''', ''' + CAST(#CLIENTKEY AS VARCHAR) + ''', ''' + CAST(#ADMISSIONKEY AS VARCHAR) + ''', ''' +
ISNULL(CAST(#PGMKEY AS VARCHAR),'') + ''', ''' + ISNULL(CAST(#PGMADMISSIONKEY AS VARCHAR),'') + ''', ''' + CAST(#STAFFKEY AS VARCHAR) + ''', ''' +
CAST(#GroupSize AS VARCHAR) + ''', ''' + CAST(#MealTime AS VARCHAR) + ''', ''' + CAST(#ApprvMgr AS VARCHAR) + ''', '''
+ CAST(#SessionNum AS VARCHAR) + ''', ''' + CAST(#FacilityKey AS VARCHAR) + ''', ''' --Added 10/30/15 JF for FC notes
+ #TtmNoteText +''',' --Added 10/30/15 JF for FC notes
+ 'NULL' + ', ' + 'NULL' + ')'
Secondly, I'm not sure you're allowed to use expressions within an EXEC. You might need to do some concatenation before passing to EXEC:
SET #SQLINSERT = #SQLINSERT + #SQLVALUES
EXEC(#SQLINSERT)

SQL Stored Procedure How to Modify and Return the Result of an Executed Dynamic Query

I have created a stored procedure that returns a single string of concatenated fields. The issue is that some of these fields may be empty strings resulting in a string much like the below:
, Mendip Road, Farnborough, Hampshire, GU14 9LS
or even
, , Farnborough, Hampshire, GU14 9LS
I really want to strip off any leading commas but I'll only know this once the query has been executed. Is there a way of executing the query, pattern-matching the commas and then removing them before finally returning the modified string?
The query itself is as follows:
SET #SQLQuery = 'SELECT TOP 1 REPLACE((ISNULL(POI,'''') + '', '' + ISNULL(Name,'''') + '', '''
+ ' + ISNULL(Settlement,'''') + '', '' + ISNULL(Cou_Unit,'''') + '', '' + ISNULL(Postcode,'''')),'', , '', '', '')'
+ ' AS ClosestAddress FROM [UKStreetsAndPlaces].[dbo].[OS_Locator] ORDER BY '
+ ' (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' * (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' + (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') * (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') ASC'
EXECUTE(#SQLQuery)
Concatenate the comma inside the ISNULL expression as follows:
ISNULL(POI + ', ','')
so your query will look like:
SET #SQLQuery = 'SELECT TOP 1 REPLACE((ISNULL(POI + '', '','''') + ISNULL(Name + '', '','''')'
+ ' + ISNULL(Settlement + '', '','''') + ISNULL(Cou_Unit + '', '','''') + ISNULL(Postcode,'''')),'', , '', '', '')'
+ ' AS ClosestAddress FROM [UKStreetsAndPlaces].[dbo].[OS_Locator] ORDER BY '
+ ' (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' * (Longitude ' + #LongitudeOperator + ' ' + CAST(ABS(#Longitude) AS VARCHAR(20)) + ')'
+ ' + (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') * (Latitude - ' + CAST(#Latitude AS VARCHAR(20)) + ') ASC'
I don't know if you need dynamic SQL for some other reason, but I think something like this should work (with no Dynamic SQL); if you're really sure you need Dynamic SQL for some other reason, then just refactor this idea into your Dynanmic Statement:
DECLARE #ClosestAddress VARCHAR(1000)
SELECT TOP 1
#ClosestAddress = ISNULL(POI + ', ','')
+ ISNULL(Name + ', ','')
+ ISNULL(Settlement + ', ','')
+ ISNULL(Cou_Unit + ', ', '')
+ ISNULL(Postcode,'')
--AS ClosestAddress
FROM [UKStreetsAndPlaces].[dbo].[OS_Locator] ORDER BY (Longitude = 12.2132) * (Longitude = 12.2132) + (Latitude - 12.2132) * (Latitude - 12.2132) ASC
IF (RIGHT(#ClosestAddress, 2) = ', ')
RETURN SUBSTRING(#ClosestAddress, 0, LEN(#ClosestAddress))
ELSE
RETURN #ClosestAddress
Why this should work: Concatenating NULL + ', ' will result in an empty string. Then we check if the string ends with ', ', and if so we return everything but the last two characters.
You could do something like Replace all Comma with space and then do LTRIM and RTRIM and replace all space with comma.
Create table Data(name varchar(10),lastname varchar(10));
insert into Data values('','Doe');
insert into Data values('Jane','Doe');
insert into Data values('Jane','');
SELECT Replace(Rtrim(Ltrim(Replace(ISNULL(name,'') +',' + ISNULL(lastname,'') + ',',',',' '))),' ',',')
from Data
something like : http://sqlfiddle.com/#!3/6a6c6/1

SQL view must return executable strings including comma of fields

Business rule - need to create view which gets all values (or some of them) form table fields into one string / varchar field.
And than I would be possible to copy thees values to other environment.
Simple example (actually using 30+ fields):
id int (autoincrement);
indicator int
name varchar
description varchar
relevance varchar
object_fk int
Some fields could be empty.
SELECT
'INSERT INTO [DM_meta].[dbo].[measure] (
id, indicator, name, description, relevance, object_fk
)
VALUES ('
+ CAST(id AS varchar(20)) + ', '
+ ISNULL(indicator,'NULL') + ', '
+ ISNULL(name,'NULL') + ', '
+ ISNULL(description,'NULL') + ', '
+ ISNULL(relevance,'NULL') + ', '
+ ISNULL(CAST(object_fk AS varchar(20)),'NULL')
+ ');
' AS _long_strings_to_coply_later_
FROM
[DM_meta].[dbo].[measure]
For the look of one expected result is fine, except description field with dots and commas:
INSERT INTO [DM_meta].dbo.measure ( id, indicator, name, description,
relevance, object_fk) VALUES ( 1103, NULL, NULL, 1.8.8.3. Lorem ipsum, where something, something and more, Yes, 70);
So the question is - how to make description field in one string without comma delimitation and dot syntax error causing.
If the target environment is a SQL Server database, you have to format your output to provide valid SQL statements.
In T-SQL strings are quoted by the single quote character (') You have to quote the strings in your output rows.
Example
SELECT
'''' + name + ''''
FROM
[DM_meta].[dbo].[measure]
It is possible, that the original string contains quotation marks. You have to escape those quotation marks:
SELECT
'''' + REPLACE(name, '''', '''''') + ''''
FROM
[DM_meta].[dbo].[measure]
In T-SQL you can escape the single quotation mark by doubling it. Run this statement to understand how escaping works:
SELECT
'''' AS OneQuotation,
'''''' AS TwoQuotations
Your query should look something like this:
SELECT
'INSERT INTO [DM_meta].[dbo].[measure] (
id, indicator, name, description, relevance, object_fk
)
VALUES ('
+ CAST(id AS varchar(20)) + ', '
+ ISNULL(indicator,'NULL') + ', '
+ ISNULL('''' + REPLACE(name, '''', '''''') + '''','NULL') + ', '
+ ISNULL('''' + REPLACE(description, '''', '''''') + '''','NULL') + ', '
+ ISNULL('''' + REPLACE(relevance, '''', '''''') + '''','NULL') + ', '
+ ISNULL('''' + REPLACE(CAST(object_fk AS varchar(20)), '''', '''''') + '''','NULL')
+ ');
' AS _long_strings_to_coply_later_
FROM
[DM_meta].[dbo].[measure]
Additional notes
Please note, that if your destination environment is a database server, you could use Linked Servers to transfer data from one server to another.
If Linked Server is not an option, please consider to use SSIS (SQL Server Integration Services) to generate or process files.
Try passing the value in quotes..
try replacing ISNULL(description,'NULL')
by char(39) + ISNULL(description,'NULL')+ char(39) or '''' + ISNULL(description,'NULL')+ ''''

Correct Amount of Spaces with concatenated person's name in SQL Server

Here is my SQL as I have it now. The first and last name should never be missing because they are required on the interface with validation. However, if the middle initial is missing, I don't want two spaces in the result; I just want one space. I could put a case statement in, but that seems like overkill if SQL already has a function for this purpose. Does anyone know if there is a function for this purpose? What would the code look like?
SELECT ISNULL(contact.firstname, '')
+ ' '
+ ISNULL(contact.middleinitial, '')
+ ' '
+ ISNULL(contact.lastname, '')
FROM dbo.contact
SELECT
ISNULL(contact.firstname, '') +
ISNULL(' ' + contact.middleinitial + ' ', ' ') +
ISNULL(contact.lastname, '')
However, you either should remove ISNULL for firstname, lastname (defined NOT NULL?) or add some trims
SELECT
LTRIM(RTRIM(
ISNULL(contact.firstname, '') +
ISNULL(' ' + contact.middleinitial + ' ', ' ') +
ISNULL(contact.lastname, '')
))
In SQL Server 2012 and up you can use CONCAT function:
SELECT CONCAT(contact.firstname, ' ' + contact.middleinitial, ' ' + contact.lastname)
FROM dbo.contact
If middleinitial is null then appending space to null value will result in null value and CONCAT will skip this null value during concatenation.
SELECT REPLACE(ISNULL(contact.firstname, '') + ' ' + ISNULL(contact.middleinitial, '') + ' ' + ISNULL(contact.lastname, '')
,' ',' ')
FROM dbo.contact

Resources