Only one expression can be specified in the select list when the subquery is not introduced with EXISTS. - DECLARE to use SPLIT_ROW - sql

I have that query:
DECLARE #test AS varchar =
(select * from users where Usr_ID in
(select Doc_Shortstringcolumn1 from Documents where Doc_ID = 11931))
And I've got an error "Only one expression can be specified in the select list when the subquery is not introduced with EXISTS." The result of select statement are three numbers, which i need to split into three rows.

(select * from users where Usr_ID in
(select Doc_Shortstringcolumn1 from Documents where Doc_ID = 11931))
you query returns multiple rows as a result variable can not contain multiple rows value.
if your query just return one value then it will return correct result
but if you change your query like below then it will works
DECLARE #test AS varchar =
(select top 1 Doc_Shortstringcolumn1 from users where Usr_ID in
(select Doc_Shortstringcolumn1 from Documents where Doc_ID = 11931)
)

Looking at your Query, It seems that you are trying to store a table into a variable which is of Varchar data type which you cannot do in SQL Server.
There are 2 possible solutions
1.
You May select only the Required filed instead of the * ad in that case if there are more than one row is returned, then only the first one will be stored in the variable and all other values will be ignored.
If this is ok with you then you may go ahead with this approach
DECLARE #test AS varchar =
select
#test = YourColumnName
from users where Usr_ID in
(
select Doc_Shortstringcolumn1 from Documents where Doc_ID = 11931
)
2
The Second approach is to use a table variable or a Temporary table to store the values so that you can store all the values and retrieve the same when needed.
Using Temp Table
select
*
into #temp
from users where Usr_ID in
(
select Doc_Shortstringcolumn1 from Documents where Doc_ID = 11931
)
using Table Variable
DECLARE #test AS TABLE
(
Column1 VARCHAR(50),
Column2 VARCHAR(50),
Column3 VARCHAR(50)
)
INSERT INTO #Test
(
Column1,
Column2,
Column3
)
select
YourColumnName1,
YourColumnName2,
YourColumnName3
from users where Usr_ID in
(
select Doc_Shortstringcolumn1 from Documents where Doc_ID = 11931
)

Related

Get the Records as per the given OrderId only

I have a table with Primary key and auto incremented column lets say "HeaderFieldID".
Now i want to get the records as per the HeaderFieldID values.
Ex:
select *
from tblHeaderField
where HeaderFieldID in (2,1,3,4,6,5)
But,by default I am getting the records by HeaderFieldID asc order. But I want records as per the given HeaderFieldID's only.
Original Table
HeaderFieldID HFName DisplayName
1 OrgName1 disp1
2 OrgName2 disp2
3 OrgName3 disp3
4 OrgName4 disp4
5 OrgName5 disp5
6 OrgName6 disp6
Thanks in Advance
I don't know if you can order by IN, because you don't know order.
So first I would split data into rows from IN and then join it to your table.
DECLARE #table TABLE (ID INT IDENTITY(1,1) NOT NULL, NR INT)
--Prodvide data to lookup
DECLARE #givenText VARCHAR(100) = '2,1,3,4,5,6,7,8,9,10,11,12,13,14,15'
-- Split requested string into rows and add unique number
;WITH xmlData (xmlData) AS (
SELECT CAST('<x>'+REPLACE(#givenText, ',', '</x><x>')+'</x>' AS XML) AS xmlData
)
INSERT INTO #table (NR)
SELECT x.value('.','INT') AS NR
FROM xmlData
CROSS APPLY xmlData.xmlData.nodes('//x') AS func(x)
--Join tables to get result
SELECT tHF.*
FROM tblHeaderField AS tHF
INNER JOIN #table AS T
ON T.NR = tHF.HeaderFieldID
ORDER BY T.ID
Isn't clear where does this list come from (as a parameter of a stored procedure or hardcoded in the SQL statement?). Try this query:
select *
from tblHeaderField
where HeaderFieldID in (2,1,3,4,6,5)
ORDER BY
CHARINDEX(','+CAST(HeaderFieldID as varchar(100))+','
,',2,1,3,4,6,5,')
SQLFiddle demo
I have solved my query.
SELECT * FROM tblHeaderField
WHERE HeaderFieldID in (5,6,2,1,3,4,7,8,9,10,11,12,13,14,15)
ORDER BY CHARINDEX(CAST(HeaderFieldID AS VARCHAR), '5,6,2,1,3,4,7,8,9,10,11,12,13,14,15')

How can I order data and add a record to the first position of the data set?

I know I can create a temp table, insert records, order it and then use union afterwards, but I'm looking for alternative routes. I tried a cte, but I had to order the entire thing which doesn't work as my unioned record doesn't stay "on top".
Basically, I have at able with Id INT, Name VARCHAR(MAX) fields and I want to ORDER BY Name before I add an entry at the row[0] position in the return set. If I order after the union, the row I wanted at row[0] gets ordered with it.
Any ideas?
You were on the right track with a union query. Force the sort with static values.
select 0 sortfield, '' name, etc
union
select 1 sortfield, name, etc
from etc
order by sortfield, name.
CREATE TABLE #temp (
idnt INT IDENTITY(2) NOT NULL --This begins the identity col with a value of 2
,Id INT
,Name VARCHAR(MAX)
)
INSERT INTO #temp
SELECT
...
FROM myTable
ORDER BY Name
CREATE TABLE #tempAPPEND (
idnt INT IDENTITY(1) NOT NULL --This begins the identity col with a value of 1
,Id INT
,Name VARCHAR(MAX)
)
INSERT INTO #tempAPPEND (Id, Name)
VALUES ('34384','Pinal Dave') -- SAMPLE VALUES
SELECT * FROM #temp
UNION
SELECT * FROM #tempAPPEND
ORDER BY idnt

How do I return the column name in table where a null value exists?

I have a table of more than 2 million rows and over 100 columns. I need to run a query that checks if there are any null values in any row or column of the table and return an ID number where there is a null. I've thought about doing the following, but I was wondering if there is a more concise way of checking this?
SELECT [ID]
from [TABLE_NAME]
where
[COLUMN_1] is null
or [COLUMN_2] is null
or [COLUMN_3] is null or etc.
Your method is fine. If your challenge is writing out the where statement, then you can run a query like this:
select column_name+' is null or '
from information_schema.columns c
where c.table_name = 'table_name'
Then copy the results into a query window and use them for building the query.
I used SQL Server syntax for the query, because it looks like you are using SQL Server. Most databases support the INFORMATION_SCHEMA tables, but the syntax for string concatenation varies among databases. Remember to remove the final or at the end of the last comparison.
You can also copy the column list into Excel and use Excel formulas to create the list.
You can use something similar to the following:
declare #T table
(
ID int,
Name varchar(10),
Age int,
City varchar(10),
Zip varchar(10)
)
insert into #T values
(1, 'Alex', 32, 'Miami', NULL),
(2, NULL, 24, NULL, NULL)
;with xmlnamespaces('http://www.w3.org/2001/XMLSchema-instance' as ns)
select ID,
(
select *
from #T as T2
where T1.ID = T2.ID
for xml path('row'), elements xsinil, type
).value('count(/row/*[#ns:nil = "true"])', 'int') as NullCount
from #T as T1

Simulate a table with multiple rows just with SELECT statement

If I can do the following select statement to create a table with one value
SELECT 'myname' AS 'Name'
this will return a table with column = Name and one value = myname
how can I work around this to return one column with multiple values from just the select statement
I don't want to do this :
DECLARE #tmp TABLE (Name varchar(50))
INSERT INTO #tmp (Name) VALUES ('myname1'),('myname2')
SELECT * FROM #tmp
Just from a single SELECT statement if possible
Or, you can use the multiple VALUES in the SELECT, like:
SELECT [Name]
FROM (VALUES ('myname1'),('myname2')) AS X([name])
If you're wanting to simulate a table with multiple rows just with SELECT statement, this can typically be done with UNION of rows:
SELECT 'myname1' AS 'Name' UNION
SELECT 'myname2' UNION
SELECT 'myname3'
-- etc
Demo: http://www.sqlfiddle.com/#!3/d41d8/12433
In case you want to simulate sequential data like in your example.You can define a recursive CTE and use it like a table.
Below code will generate 10 records
;With Users as
(
Select 1 as ID, CAST('Username1' AS varchar(25)) as Name
union all
Select ID + 1 , CAST('Username'+CAST(ID+1 AS varchar(5) ) AS varchar(25))
from Users
where ID < 10
)
SELECT * FROM Users
Here is SQL Fiddle http://www.sqlfiddle.com/#!3/d41d8/12452
But CTE cannot be used in multiple statements.If you need to use it in multi statements. Then insert data from CTE to Temp Table or Table Variable.

Add empty row to query results if no results found

I'm writing stored procs that are being called by a legacy system. One of the constraints of the legacy system is that there must be at least one row in the single result set returned from the stored proc. The standard is to return a zero in the first column (yes, I know!).
The obvious way to achieve this is create a temp table, put the results into it, test for any rows in the temp table and either return the results from the temp table or the single empty result.
Another way might be to do an EXISTS against the same where clause that's in the main query before the main query is executed.
Neither of these are very satisfying. Can anyone think of a better way. I was thinking down the lines of a UNION kind of like this (I'm aware this doesn't work):
--create table #test
--(
-- id int identity,
-- category varchar(10)
--)
--go
--insert #test values ('A')
--insert #test values ('B')
--insert #test values ('C')
declare #category varchar(10)
set #category = 'D'
select
id, category
from #test
where category = #category
union
select
0, ''
from #test
where ##rowcount = 0
Very few options I'm afraid.
You always have to touch the table twice, whether COUNT, EXISTS before, EXISTs in UNION, TOP clause etc
select
id, category
from mytable
where category = #category
union all --edit, of course it's quicker
select
0, ''
where NOT EXISTS (SELECT * FROM mytable where category = #category)
An EXISTS solution is better then COUNT because it will stop when it finds a row. COUNT will traverse all rows to actually count them
It's an old question, but i had the same problem.
Solution is really simple WITHOUT double select:
select top(1) WITH TIES * FROM (
select
id, category, 1 as orderdummy
from #test
where category = #category
union select 0, '', 2) ORDER BY orderdummy
by the "WITH TIES" you get ALL rows (all have a 1 as "orderdummy", so all are ties), or if there is no result, you get your defaultrow.
You can use a full outer join. Something to the effect of ...
declare #category varchar(10)
set #category = 'D'
select #test.id, ISNULL(#test.category, #category) as category from (
select
id, category
from #test
where category = #category
)
FULL OUTER JOIN (Select #category as CategoryHelper ) as EmptyHelper on 1=1
Currently performance testing this scenario myself so not sure on what kind of impact this would have but it will give you a blank row with Category populated.
This is #swe's answer, just reformatted:
CREATE FUNCTION [mail].[f_GetRecipients]
(
#MailContentCode VARCHAR(50)
)
RETURNS TABLE
AS
RETURN
(
SELECT TOP 1 WITH TIES -- Returns either all Priority 1 rows or, if none exist, all Priority 2 rows
[To],
CC,
BCC
FROM (
SELECT
[To],
CC,
BCC,
1 AS Priority
FROM mail.Recipients
WHERE 1 = 1
AND IsActive = 1
AND MailContentCode = #MailContentCode
UNION ALL
SELECT
*,
2 AS Priority
FROM (VALUES
(N'system#company.com', NULL, NULL),
(N'author#company.com', NULL, NULL)
) defaults([To], CC, BCC)
) emails
ORDER BY Priority
)
I guess you could try:
Declare #count int
set #count = 0
Begin
Select #count = Count([Column])
From //Your query
if(#Count = 0)
select 0
else //run your query
The downside is that you're effectively running your query twice, the up side is that you're skiping the temp table.
To avoid duplicating the selecting query, how about a temp table to store the query result first? And based on the temp table, return default row if the temp table is empty or return the temp when it has result?