Join query with user provided data-T-sql - sql-server

I have a requriment where user will provide many Ids(in Hundres/thousands) in a Text area in vb.net app, I need to use these IDs in T-Sql(Sql Server) to get the data. I dont want to save these Ids in any database table. Just want to pass using a paramater (type of varchar(max)) and use in the procedure.
actually, only read access is permitted for the vb application users.It is Sql-2005 database.Id field is atleaset 12 to 15 characters length.The user will copy/paste data from other source may be CSV or Excel file.
any idea how can i achive this.
any help is appreciated.
Thanks

If you do not want to use Table Valued Parameters, as suggested elsewhere, and you don't want to store the ID's in a temporary table, you can do the following.
Assuming your ID's are integer values, that are separated by commas, in the parameter string, you can use the LIKE operator in your SQL-statement's WHERE filter:
Say you have a parameter, #IDs of type varchar(max). You want to get only those records from MyTable where the ID-column contains a value that has been typed into the #IDs-parameter. Then your query should look something like this:
SELECT * FROM MyTable
WHERE ',' + #IDs + ',' LIKE '%,' + CAST(ID AS varchar) + ',%'
Notice how I prepend and append an extra comma to the #IDs parameter. This is to ensure that the LIKE operator will still work as expected for the first and last ID in the string. Make sure to take the nescessary precautions against SQL injection, for example by validating that users are only allowed to input integer digits and commas.

Try using CHARINDEX:
DECLARE #selectedIDs varchar(max) = '1,2,3'
Set #selectedIDs = ',' + #selectedIds + ',' --string should always start and end with ','
SELECT * FROM YourTable
WHERE CHARINDEX(',' + CAST(IDColumn as VARCHAR(10)) + ',', #selectedIds) > 0

Related

SQL Server : display data/column from SELECT statement

I have a table with data that holds a bunch of HTML attributes.
For example: '<HTML><BODY></BODY></HTML>'
I would like to be able to write a SELECT statement that can grab those values, but display them modified.
So instead of displaying
'<HTML><BODY>DATA</BODY></HTML>'
I want to show:
'<HTML>
<BODY>DATA</BODY>
</HTML>'
Essentially, breaking out each one to a new line, based on finding a '>' value, without modifying the data.
I can't seem to find a way to do this. I tried looking into STRING_SPLIT, but I can't get that to apply from the SELECT part.
Any suggestions where I look?
Edit 2/22 - it appears REPLACE gets me further, but when reviewing this more, it may not be possible.
How would SQL know to break out to a new line when the ending HTML tag appears?
It's almost like I need to use a RegEx in here...
REPLACE(TD.DefDetails, '</', CHAR(13) + CHAR(10) + '</') As DefDetails
STRING_SPLIT can split a single column into multiple rows. STRING_SPLIT does require SQL Server Version 2016+. The following snippet does show an example for this scenario.
USE tempdb;
GO
DECLARE #HTMLString AS VARCHAR(100) = '<HTML><BODY></BODY></HTML>';
SELECT *
FROM STRING_SPLIT(#HTMLString,'>');
Actually appears this is done using REPLACE.
REPLACE(Table.DefDetails, '>', '>'+ CHAR(13) + CHAR(10)) As DefDetails
Demo on db<>fiddle
You can achieve it in this way
SELECT REPLACE('<HTML><BODY></BODY></HTML>', '>', '>'+ CHAR(13))
Or if you want to get the value into rows, you can do this way.
Select value + '>'
from STRING_SPLIT('<HTML><BODY></BODY></HTML>', '>')
where value <> ''
Output

SQL Result to XML (Specific Layout)

I have a table in SQL that contains a list of settings for an application per serverID
I want write a SQL statement that produce a specific XML layout.
The basic SQL statement to retrieve this data:
SELECT SettingName, SettingValue
FROM dbo.ServerSettings
WHERE ServerID = #ServerID
I just need to know the correct FOR XML options.
I want to get back a result like the following. Basically using the value of the SettingName field to be the name of the node.
<ROOT>
<COSTRECOVERYSYSTEM_CONNECTION_STRING></COSTRECOVERYSYSTEM_CONNECTION_STRING>
<COSTRECOVERYSYSTEM_EXTRACT_INTERVAL>60</COSTRECOVERYSYSTEM_EXTRACT_INTERVAL>
<COSTRECOVERYSYSTEM_FILE_DATESTAMP>yyyyMMdd</COSTRECOVERYSYSTEM_FILE_DATESTAMP>
<COSTRECOVERYSYSTEM_FILE_EXTENSION>txt</COSTRECOVERYSYSTEM_FILE_EXTENSION>
<COSTRECOVERYSYSTEM_FILE_NAME>txt</COSTRECOVERYSYSTEM_FILE_NAME>
<COSTRECOVERYSYSTEM_FILE_PATH>txt</COSTRECOVERYSYSTEM_FILE_PATH>
</ROOT>
As in any other query you cannot use a column's value as the output column name. This would need some dynamically created statement and EXEC() for its execution.
But you might do something along this:
DECLARE #tbl TABLE(SettingName VARCHAR(100),SettingValue VARCHAR(100));
INSERT INTO #tbl VALUES ('Setting1','1'),('Setting2','2'),('ForbiddenValue','Huh! What about & and <?');
SELECT CAST((
SELECT '<' + UPPER(t.SettingName) + '>' +
--this embedded FOR XML will implicitly do the escaping for you
(SELECT t.SettingValue AS [*] FOR XML PATH('')) +
'</' + UPPER(t.SettingName) + '>'
FROM #tbl t
FOR XML PATH(''),TYPE
).value('.','nvarchar(max)') AS XML)
FOR XML PATH('ROOT');
In general I would never create XML with string methods. There are so many possible draw backs and traps. But in this case it might be the best choice.
Hint: Be sure, that the setting names are valid XML element names. There are some XML element naming rules
You can see these links for more information:
1. https://learn.microsoft.com/en-us/sql/relational-databases/xml/for-xml-sql-server?view=sql-server-2017
2. https://www.red-gate.com/simple-talk/sql/learn-sql-server/using-the-for-xml-clause-to-return-query-results-as-xml/

How to use an evaluated expression in SQL IN clause

I have an application that takes a comma separated string for multiple IDs to be used in the 'IN' clause of a SQL query.
SELECT * FROM TABLE WHERE [TABLENAME].[COLUMNNAME]
IN
((SELECT '''' + REPLACE('PARAM(0, Enter ID/IDS. Separate multiple ids by
comma., String)', char(44), ''',''') + ''''))
I have tested that PARAM gets the string entered e.g. 'ID1, ID2' but SELECT/REPLACE does not execute. The statement becomes,
SELECT * FROM TABLE WHERE [TABLENAME].[COLUMNNAME]
IN
((SELECT '''' + REPLACE('ID1,ID2', char(44), ''',''') + ''''))
I am trying to achieve,
SELECT * FROM TABLE WHERE [TABLENAME].[COLUMNNAME]
IN ('ID1', 'ID2')
The query does not return any results/errors. I am confident the corresponding records are in the database I am working with. Not sure how to fix this.
You can't do it like this. The IN operator expects a list of parameters separated by comma, but you supply it with a single parameter that happens to contain a comma delimited string:
If you are working on SQL Server version 2016 or higher, you can use the built in string_split to convert the delimited string into a table.
SELECT *
FROM TABLE
WHERE [TABLENAME].[COLUMNNAME]
IN STRING_SPLIT(#CommaDelimitedString, ',')
For older versions, there are multiple user defined functions you can choose from, my personal favorite is Jeff Moden's DelimitedSplit8K. For more options, read Aaron Bertrand's Split strings the right way – or the next best way.

Is there a SQL Server collation option that will allow matching different apostrophes?

I'm currently using SQL Server 2016 with SQL_Latin1_General_CP1_CI_AI collation. As expected, queries with the letter e will match values with the letters e, è, é, ê, ë, etc because of the accent insensitive option of the collation. However, queries with a ' (U+0027) do not match values containing a ’ (U+2019). I would like to know if such a collation exists where this case would match, since it's easier to type ' than it is to know that ’ is keystroke Alt-0146.
I'm confident in saying no. The main thing, here, is that the two characters are different (although similar). With accents, e and ê are still both an e (just one has an accent). This enables you (for example) to do searches for things like SELECT * FROM Games WHERE [Name] LIKE 'Pokémon%'; and still have rows containing Pokemon return (because people haven't used the accent :P).
The best thing I could suggest would be to use REPLACE (at least in your WHERE clause) so that both rows are returned. That is, however, likely going to get expensive.
If you know what columns are going to be a problem, you could, therefore, add a PERSISTED Computed Column to that table. Then you could use that column in your WHERE clause, but display the one the original one. Something like:
USE Sandbox;
--Create Sample table and data
CREATE TABLE Sample (String varchar(500));
INSERT INTO Sample
VALUES ('This is a string that does not contain either apostrophe'),
('Where as this string, isn''t without at least one'),
('’I have one of them as well’'),
('’Well, I''m going to use both’');
GO
--First attempt (without the column)
SELECT String
FROM Sample
WHERE String LIKE '%''%'; --Only returns 2 of the rows
GO
--Create a PERSISTED Column
ALTER TABLE Sample ADD StringRplc AS REPLACE(String,'’','''') PERSISTED;
GO
--Second attempt
SELECT String
FROM Sample
WHERE StringRplc LIKE '%''%'; --Returns 3 rows
GO
--Clean up
DROP TABLE Sample;
GO
The other answer is correct. There is no such collation. You can easily verify this with the below.
DECLARE #dynSql NVARCHAR(MAX) =
'SELECT * FROM (' +
(
SELECT SUBSTRING(
(
SELECT ' UNION ALL SELECT ''' + name + ''' AS name, IIF( NCHAR(0x0027) = NCHAR(0x2019) COLLATE ' + name + ', 1,0) AS Equal'
FROM sys.fn_helpcollations()
FOR XML PATH('')
), 12, 0+ 0x7fffffff)
)
+ ') t
ORDER BY Equal, name';
PRINT #dynSql;
EXEC (#dynSql);

How can I append a column in SQL?

I've tried different things in SQL Server 2012 to append the columns. CONCAT merges the columns look like this: catdogparrot whereas I want it be in a list like:
cat
dog
parrot
I've also tried the + in SQL, giving me the same result. I saw '||' as well, but for some reason it says wrong syntax at the second pipe. Is there a way to append a column to a new one? Or would I have to create a new column from the multiple columns? These columns are in the same table. Any suggestions are advice are greatly appreciated, thanks!
I'm not sure what you are trying to do, but you could try to use
CONCAT(' - ', `column1`, ' - ', `column2`, ' - ', ... `column999`)
Eventually this could help you: You can set the separator to any sequence, even to CHAR(13)+CHAR(10), which is a windows line break.
DECLARE #dummyTbl TABLE(animal VARCHAR(10));
INSERT INTO #dummyTbl
VALUES('cat'),('dog'),('parrots');
DECLARE #separator VARCHAR(5)= ' / ';
SELECT STUFF(
(
SELECT #separator + animal
FROM #dummyTbl AS dt
FOR XML PATH(''),TYPE
).value('.','varchar(max)'),1,LEN(#separator),'');

Resources