How to put result of one column inside a string variable? - sql

I try to select number of rows and then put them into string variable such as 1,2,3,4,5, but get this error :
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
I use MSSQL SERVER
DECLARE #CodeNameString VARCHAR(MAX)
SELECT #CodeNameString = STUFF(
(
SELECT dbo.CharterReference.TicketNo+','
FROM dbo.CharterReference
),
1,
1,
''
)
SELECT #CodeNameString
How can i fix this?

If you want the values in #CharterReference, you can use the following
Declare #CharterReference table (TicketNo int)
Insert Into #CharterReference values
(1),(2),(3),(4),(5),(6),(7),(8)
Declare #CodeNameString varchar(Max) = '>>>'
Select #CodeNameString =replace(concat(#CodeNameString ,',',TicketNo),'>>>,','')
From #CharterReference
Where TicketNo between 1 and 5
Order By TicketNo
Select #CodeNameString
Returns
1,2,3,4,5
Or you can use a little XML
Select #CodeNameString=Stuff((Select ',' +cast(TicketNo as varchar(25))
From #CharterReference
Where TicketNo between 1 and 5
For XML Path ('')
),1,1,'')

The error message is complaining because you have multiple rows returned, and that is not allowed in the way you have done this.
Rearranging to a normal looking select statement, and then lopping off the last comma afterwards would work around this:
DECLARE #CodeNameString VARCHAR(MAX);
set #CodeNameString = '';
SELECT #CodeNameString = TicketNo + ','
FROM dbo.CharterReference;
SELECT left(#CodeNameString, len(#CodeNameString)-1) as CodeNameString;

The SQL-based solution requires you to use recursive SQL for this. The syntax is typically DBMS-specific, and guessing by the syntax you're using in the example, O believe your engine calls this feature "recursive CTE".
The alternative is to cursor over the result set with the individual row and construct the string append in your client program.
Yet another alternative is to use the PL/SQL dialect of your system. You can then write an SQL procedure where you do the cursoring over the result set and the string appending. You can expose this SQL procedure as a callable module to your client programs.

Related

Can you concatenate a string value multiple times in a PostgreSql SELECT statement?

In Sql Server you can run the following query to combine values from multiple rows into a single string variable.
DECLARE #x NVARCHAR(MAX) = N'';
SELECT TOP 5 #x = #x + name + ', '
FROM sys.objects
SELECT #x
Which results in
"sysrscols, sysrowsets, sysclones, sysallocunits, sysfiles1,"
Is there a way to do something similar in PostgreSql? I've tried creating a PostgreSql function that does a SELECT INTO stringVariable but that is only resulting in a single row's worth of values.
Not exactly. The code you have in SQL Server is not actually guaranteed to work. In Postgres, you would use:
select string_agg(name, ', ')
from sys.objects;
If you have a sys.objects table.
Note that in SQL Server, you should do the same thing:
select string_agg(name, ', ')
from sys.objects;
as demonstrated in this SQL Fiddle.
As a note: Your use of the variable is directly contradicted by the documentation:
If a SELECT statement returns more than one row and the variable references a non-scalar expression, the variable is set to the value returned for the expression in the last row of the result set.
That said, I know what you are doing actually works in practice. But I would recommend using string_agg() or in earlier versions using XML for string concatenation.

T-SQL get substring

I am looking to get an order number from a column named KEY_Ref, this ref column have various contents, but some rows look like this
LINE_NO=15^ORDER_NO=176572^RELEASE_NO=1^
Now I am interested in getting the value for ORDER_NO (176572 in this case)
How would I (In SQL Server) go about getting this (Or other) value from the main string
The logic is always
key1=value1^key2=value2^key3=value3^
You can use string_split():
select t.*, s.orderno
from t outer apply
(select stuff(s.value, 1, 9, '') as orderno
from string_split(t.key_ref, '^') s
where s.value like 'ORDER_NO=%'
) s;
Here is a db<>fiddle.
this is going to be a bit lengthy answer however if your SQL server version doesn't support string_split function you may use this.
declare #str varchar(100) = 'LINE_NO=15^ORDER_NO=176572^RELEASE_NO=1^'
declare #substr1 varchar(50) = substring(#str,charindex('^',#str)+1,len(#str))
declare #substr2 varchar(50) = substring(#substr1,charindex('=',#substr1)+1,charindex('^',#substr1)-charindex('=',#substr1)-1)
select #substr2 as 'order number'
the final variable will produce the desired value and you must merge the above queries to a single query that can fetch the value from the table in a single select statement.
this will work only if the pattern doesn't deviate from the one you've mentioned.

How to declare a local variable and give it the value of the first row of a temptable ? (SQL SERVER)

I have a procedure on sql server, in this procedure I have a temp_table that contains only one row and I would like to declare a local variable in that procedure and give it the value in the temp_table :
Let's suppose my temp_table has one row and 2 columns :
Variable Variable2
"hello_world" 3
I tried Declare #variable varchar(50) = #temp_table.variable
but unsurprisingly it's not working.
I would like that line of code to put the value "hello_world" in the local variable #variable.
Do you know how to do that without using a subquery select top 1 if it's possible ?
If your table only has one row, you can use:
Declare #variable varchar(50)
SELECT #variable = variable from #temp_table
But if your table has multiple rows you need to use order by as well and fetch the top 1 value
SELECT TOP 1 #variable = variable from #temp_table order by col -- col is the column for which you want the top value
Like so:
DECLARE #variable VARCHAR(50) = (SELECT variable FROM #temp_table);
What's "good" about this approach is that, if for some reason you are mistaken about the table having only one row, the query will error out:
Msg 512, Level 16, State 1, Line 1 Subquery returned more than 1
value. This is not permitted when the subquery follows =, !=, <, <= ,
>, >= or when the subquery is used as an expression.
And that's arguably exactly what you want. Using TOP(1) with no ORDER BY or a separate SELECT #variable = variable ... will select one arbitrary value from the table -- that might be harmless, or then again it might be a really hard to debug issue.

How to get value inside quotes in SQL

I want to separate a fixed expression in SQL in order to get the string value inside ' '.
For example in the following SQL:
declare #value varchar(60)
set #value = 'a.[country] LIKE ''US'''
I would like to store separately the information US, is there a way to do it?
Thank you in advance.
You can try this
declare #value varchar(60)
set #value = 'a.[country] LIKE ''US'''
select left(Right(#value,3),2)
--OR this
select substring(Right(#value,3), 1, 2)
The question seems incomplete, but based on the question I suggest to use some Delimiter with the dynamic string and use combination of LEFT, CHARINDEX and SUBSTRING in SQL to fetch values out of SQL.
Example
Following is not the best example, but just explaining how to use it:
e.g
declare #value varchar(60)
set #value = 'a.[country] LIKE §''US'''
SELECT LEFT(SUBSTRING(#value,
CHARINDEX('§', #value) + 1, 100),
CHARINDEX('§', #value) - 1)
Output
'US'
There are already some example about this on StackOverflow.
If you haven't checked out yet other StackOverflow posts, you can refer following:
How to extract this specific substring in SQL Server?

How to convert T-SQL that deals with OPENXML, WITH and BIGINT?

I'm trying to convert a procedure to use in SQL Azure. I first got an error on OPENXML saying it's not supported on SQL Azure, then I find out it can be replaced with nodes.
But I'm not sure how to convert the WITH (Id BIGINT '.') part. I know WITH creates a subquery but what is the '.' doing here?
CREATE Procedure [dbo].[DocsR]
#ids xml -- <Ids><Id>1</Id><Id>2</Id></Ids>
AS
BEGIN
SET NOCOUNT ON;
DECLARE #IdsXml xml
exec sp_xml_preparedocument #IdsXml OUTPUT, #Ids
SELECT
DoctId,
DocNm
FROM
Docs
WHERE
--DocId IN (SELECT Id FROM OPENXML(#IdsXml, '/Ids/Id', 2) WITH (Id BIGINT '.'))
DocId IN (SELECT Id FROM #IdsXml.nodes('/Ids/Id') WITH (Id BIGINT '.'))
END
GO
Error:
Incorrect syntax near the keyword 'with'. If this statement is a common
table expression, an xmlnamespaces clause or a change tracking context clause,
the previous statement must be terminated with a semicolon.
Try the following:
SELECT
DoctId,
DocNm
FROM
Docs
WHERE
DocId IN (SELECT Id = node.value('.', 'INT')
FROM #IdsXml.nodes('/Ids/Id') AS R(node))