How to have a NULL instead of No Value from a query - sql

I had a query like:
SELECT ISNULL(S.Name+'.'+T.Name,'Table Not Found')
FROM DataProfile.Tables T
INNER JOIN DataProfile.Schemas S ON T.schemaId=S.Id
WHERE S.Name+'.'+T.Name=#TableName
Then I tried
IIF(LEN(S.Name+'.'+T.Name)>0,S.Name+'.'+T.Name,NULL)
But when it doesn't find the named table returns not output, Value or Null value or anything I can work on.
This is going to be used as a crosscheck.
Does anybody have any idea?

Thanks for those who payed attention to what I exactly asked and for their responses.
Here the way I tried:
DECLARE #Check NVARCHAR(MAX) = 'TABLE DOES NOT FOUND'
SELECT #Check= S.Name + '.' + T.Name
FROM DataProfile.Tables T
INNER JOIN DataProfile.Schemas S ON T.schemaId=S.Id
WHERE S.Name+'.'+T.Name=#TableName
SELECT #CHECK
And That Worked for me

this will always return a row:
select v.TableName, ISNULL(found.result, 'not found') result
from (values(#TableName))v(TableName)
outer apply (
select CAST('found' as nvarchar(11)) result
from DataProfile.Tables T
join DataProfile.Schemas S ON T.schemaId=S.Id
where S.Name+'.'+T.Name=v.TableName
)found

you should try this
SELECT CASE WHEN (LEN(S.Name + '.' + T.Name))> 1 THEN S.Name + '.' + T.Name ELSE NULL END
So you qry will look like
SELECT CASE
WHEN (LEN(S.Name + '.' + T.Name))> 1 THEN
S.Name + '.' + T.Name
ELSE
NULL -- Here use any expresion which you want
END
FROM DataProfile.Tables T
INNER JOIN DataProfile.Schemas S ON T.schemaId=S.Id
WHERE S.Name+'.'+T.Name=#TableName
Here you are using ISNULL(S.Name+'.'+T.Name,'Table Not Found') which never return false part due to if S.Name and T.Name both are null then still that value will be '.'

Try doing it this way:
with table_qry as
(
select S.Name as SName, T.Name as TName
from DataProfile.Tables T
inner join DataProfile.Schemas S
on T.SchemaId = S.Id
where S.Name+'.'+T.Name = #TableName
)
select case when (select count(1) from table_qry) > 0 then
SName+'.'+TName else 'Table Not Found' end as TableName
from table_qry;
There are more elegant ways of doing it, but this should work just fine for you.

Related

Compare table columns and display differences in error message in SQL Server 2014

I am trying to write some SQL which will compare two SQL server tables and display any differences in columns in an error message. There could be multiple differences so I need each of these mentioned in the error message. I've made a start on this but keen for some pointers on how I can capture exact differences.
Thanks,
SELECT name,
object_id
INTO #sysTbl
FROM sys.tables
ORDER BY name
SELECT t.name AS 't_name',
cols.name AS 'c_name',
cols.user_type_id,
typ.name as user_type_name,
cols.max_length,
cols.is_nullable
INTO #sysCols
FROM #sysTbl t
INNER JOIN sys.all_columns AS cols ON t.object_id = cols.object_id
INNER JOIN sys.types AS typ ON cols.user_type_id = typ.user_type_id
SELECT *
INTO #errorTbl
FROM
(
SELECT *
FROM dbo.[metaDataFile]
EXCEPT
SELECT *
FROM #sysCols
UNION
SELECT *
FROM #sysCols
EXCEPT
SELECT *
FROM dbo.[metaDataFile]
) err
DECLARE #errStr VARCHAR(MAX)
--build Error Message
select #errStr = 'There is a mismatch on' + stuff((select ',' + ' table ' + t_name +' on column ' + c_name
FROM #errorTbl t2
FOR XML PATH('')),1,1,'')
IF EXISTS
(
SELECT *
FROM #errorTbl
)
RAISERROR (#errStr,
16, -- Severity,
1, -- State,
N'Failure due to data mismatch');
ELSE
BEGIN
PRINT 'Success - Data Matches'
END
This might be overly simplified but here's an effort using information schema:
select *
from INFORMATION_SCHEMA.COLUMNS
where TABLE_CATALOG='DB NAME'
and TABLE_NAME='TABLE NAME'
This will give all of the column info and metadata regarding the table in question.
Now try this for both:
select
t1.COLUMN_NAME
,DataType_NoMatch = case when t1.DATA_TYPE <> t2.DATA_TYPE then 1 else 0 end
from
(
select *
from INFORMATION_SCHEMA.COLUMNS
where TABLE_CATALOG='DB NAME'
and TABLE_SCHEMA = 'SCHEMA'
and TABLE_NAME='TABLE'
) t1
join
(
select *
from INFORMATION_SCHEMA.COLUMNS
where TABLE_CATALOG='DBANME'
and TABLE_SCHEMA = 'SCHEMA'
and TABLE_NAME='TABLE2'
) t2 on t1.COLUMN_NAME=t2.COLUMN_NAME
and work your way through the attributes that you want to compare. I gave you an example for data type.
Added based on Cross apply comment:
select
t1.COLUMN_NAME
,ca.*
from
(
select *
from INFORMATION_SCHEMA.COLUMNS
where TABLE_CATALOG='DB NAME'
and TABLE_SCHEMA = 'dbo'
and TABLE_NAME='DimOrganization'
) t1
join
(
select *
from INFORMATION_SCHEMA.COLUMNS
where TABLE_CATALOG='DB NAME'
and TABLE_SCHEMA = 'bak'
and TABLE_NAME='DimOrganization'
) t2 on t1.COLUMN_NAME=t2.COLUMN_NAME
cross apply
(select Metadata = 'DataType' ,TestPassFail = case when t1.DATA_TYPE <> t2.DATA_TYPE then 1 else 0 end
union all
select [Column] = 'CharMaxLen' ,TestPassFail = case when t1.CHARACTER_MAXIMUM_LENGTH <> t2.CHARACTER_MAXIMUM_LENGTH then 1 else 0 end
) ca
where ca.TestPassFail=1

some weird signs appearing on SQL SERVER Query output

i have written a SELECT Query on SQL SERVER 2014 . I have got the desired output . but an apostrophe symbol(') appearing on 'TaskAction' field data(at the end of each data). here it is my script:
SELECT
WOtask.PK,
WOPK,
TaskNo,
TaskAction =
CASE
WHEN WOTask.AssetPK IS NOT NULL THEN '<b>' + Asset.AssetName + ' [' + Asset.AssetID + ']</b> ' + CASE
WHEN Asset.Vicinity IS NOT NULL AND
Asset.Vicinity <> '''' THEN RTRIM(Asset.Vicinity) + ': '
ELSE ''''
END + WOtask.TaskAction + CASE
WHEN CONVERT(varchar, ValueLow) IS NOT NULL AND
CONVERT(varchar, ValueHi) IS NOT NULL AND
Spec = 1 THEN ' (Range: '' + CONVERT(VARCHAR,CONVERT(FLOAT,ISNULL(ValueLow,0))) + '' - '' + CONVERT(VARCHAR,CONVERT(FLOAT,ISNULL(ValueHi,0))) + )'
ELSE ''''
END
ELSE WOtask.TaskAction + CASE
WHEN CONVERT(varchar, ValueLow) IS NOT NULL AND
CONVERT(varchar, ValueHi) IS NOT NULL AND
Spec = 1 THEN ' (Range: '' + CONVERT(VARCHAR,CONVERT(FLOAT,ISNULL(ValueLow,0))) + '' - '' + CONVERT(VARCHAR,CONVERT(FLOAT,ISNULL(ValueHi,0))) + )'
ELSE ''''
END
END,
Rate,
Measurement,
Initials,
Fail,
Complete,
Header,
LineStyle,
WOtask.Comments,
WOtask.NotApplicable,
WOTask.Photo1,
WOTask.Photo2
FROM WOtask WITH (NOLOCK)
LEFT OUTER JOIN Asset WITH (NOLOCK)
ON Asset.AssetPK = WOTask.AssetPK
LEFT OUTER JOIN AssetSpecification
ON AssetSpecification.PK = WOTask.AssetSpecificationPK
WHERE (WOPK IN (SELECT
WOPK
FROM WO WITH (NOLOCK)
LEFT OUTER JOIN Asset WITH (NOLOCK)
ON Asset.AssetPK = WO.AssetPK
LEFT OUTER JOIN AssetHierarchy WITH (NOLOCK)
ON AssetHierarchy.AssetPK = WO.AssetPK
WHERE WO.WOPK = 10109)
)
ORDER BY WOPK, TaskNo
now please check my output and error
please help to solve this issue. Thanks in Advance.
As noted in comments, use ELSE '' instead of ELSE ''''. The reason is that within a pair of single quotes, then '' tells SQL to escape a single quote into your output.
For instance, to show the output User's, you would need SELECT 'User''s'.

How do I select an extra row for each row in the result set in SQL?

I have the below query:
SELECT '['+name+']' FROM sys.schemas
Where name <> 'dbo' AND name <> 'guest' AND name <> 'INFORMATION_SCHEMA'
....
The result of this query is simple:
I need an extra row with text 'GO' after every record like this:
Is there a way to do this? I tried with a foreach statement, but I was unable to replicate the desired results.
Just add Go statement to the Dynamic code by hitting ENTER key and see the result pasting in SSMS. This will populate with GO statement in Next line.
You should also use QUOTENAME rather than concatenating the square brackets yourself (to work correctly for names containing ]) and the where clause can be simplified with NOT IN.
SELECT QUOTENAME(name) +'
GO
'
FROM sys.schemas
WHERE name NOT IN ('dbo', 'guest', 'INFORMATION_SCHEMA')
If you just want carriage returns and "GO" after each line, you can put that in the SELECT:
SELECT '[' + name + ']
GO'
FROM sys.schemas
Where name <> 'dbo' AND name <> 'guest' AND name <> 'INFORMATION_SCHEMA'
....
This is not exactly what you are asking for, but it might do what you need.
You can do it by using UNION ALL to populate these extra values, and the use CASE EXPRESSION in the ORDER BY clause for this specific order:
SELECT t.name_col
FROM(
SELECT '['+name+']' as name_col,'['+name+']' as ord_col
FROM sys.schemas
Where name NOT IN('dbo','guest','INFORMATION_SCHEMA')
UNION ALL
SELECT 'GO','['+name+']' as ord_col
FROM sys.schemas
Where name NOT IN('dbo','guest','INFORMATION_SCHEMA')) t
ORDER BY t.ord_col,
CASE WHEN t.name_col = 'GO' THEN 1 ELSE 0 END
select c.txt
from sys.schemas cross apply (values ('['+name+']'),('GO')) c(txt)
where name not in ('dbo','guest','INFORMATION_SCHEMA')
Guaranteed order
select c.txt
from sys.schemas s cross apply (values ('['+name+']',1),('GO',2)) c(txt,ord)
where s.name not in ('dbo','guest','INFORMATION_SCHEMA')
order by s.name,c.ord
Here is another way with cross apply values
SELECT B.*
FROM (SELECT '[' + NAME + ']' AS NAME1,
'GO' AS GO1
FROM SYS.SCHEMAS
WHERE NAME NOT IN ( 'DBO', 'GUEST', 'INFORMATION_SCHEMA' ))A
CROSS APPLY ( VALUES(NAME1),
(GO1) ) B(NAME1)
Newline explicitely inside the column:
SELECT QUOTENAME(name)+CHAR(10)+CHAR(13)+'GO'
FROM sys.schemas
WHERE name <> 'dbo' AND name <> 'guest' AND name <> 'INFORMATION_SCHEMA';
Newline in a new row:
SELECT
lot
FROM
(
SELECT name=CAST(QUOTENAME(name) AS VARCHAR(256)),extra_line=CAST('GO' AS VARCHAR(256))
FROM sys.schemas
WHERE name <> 'dbo' AND name <> 'guest' AND name <> 'INFORMATION_SCHEMA'
) as p
UNPIVOT(lot FOR l IN (name,extra_line)) AS up;
We can use CONCAT also instead of + for SQL2008+
SELECT CONCAT('[', name ,'] GO ')
FROM sys.schemas
WHERE name <> 'dbo' AND name <> 'guest' AND name <> 'INFORMATION_SCHEMA';
How about something like:
select name from (
SELECT 2 * rowid as r,
'['+name+']' as name
FROM sys.schemas
union
select 2 * rowid + 1, 'GO' FROM sys.schemas
)s
order by r

How to remove first and last charcter if character is ',' of name in Sql query

I combine two column value with ',' using below query.
SELECT
RTRIM(LTRIM(REPLACE(
IsNull(tbl1 .Reason,'') + ',' + IsNull(tbl2.OtherReason,''),',' ,'')))
FROM tbl1
LEFT JOIN tbl2 ON tbl2.OtherReasonId = tbl1.ReasonId
Now issue is that it remove all ',' using above query and I want to just remove last and first ','.
I have combine two column. Now
if tbl1 .Reason is null then it display output as " ,tbl2.OtherReason " and if tbl2.OtherReason is null the output is "tbl1 .Reason,"
Before above query, I also try with below query:
SELECT
IsNull(tbl1.Reason,'') + ',' + IsNull(tbl2.OtherReason,'')
FROM tbl1
LEFT JOIN tbl2 ON tbl2.OtherReasonId = tbl1.ReasonId
Thanks,
HItesh
You can use a case in the middle to check if the values are null or not.
declare #a nvarchar(5)
,#b nvarchar(5)
set #a = 'abc'
set #b = null--'123'
select isnull(#a, '') + case when #a is not null and #b is not null then ',' else '' end + isnull(#b, '')
Try this:
SELECT
CASE
WHEN tbl1.Reason IS NULL
THEN
CASE
WHEN tbl2.Reason IS NULL
THEN ''
ELSE LTRIM(RTRIM(tb2.Reason))
END
ELSE tbl1.Reason +
CASE
WHEN tbl2.Reason IS NULL
THEN ''
ELSE ',' + LTRIM(RTRIM(tb2.Reason))
END
END
FROM tbl1
LEFT JOIN tbl2 ON tbl2.OtherReasonId = tbl1.ReasonId
You can concatenate a comma to the first value in case that second value is not null :
SELECT
IsNull(tbl1.Reason + case when tbl2.OtherReason is null then '' else ',' end, '') +
IsNull(tbl2.OtherReason,'')
FROM tbl1
LEFT JOIN tbl2 ON tbl2.OtherReasonId = tbl1.ReasonId

Conditionals in transact-sql select column lists

I've got a query that looks a bit like this:
select
records.id,
contacts.name + ' (' + contacts.organization + ')' as contact,
from records
left join contacts on records.contact = contacts.contactid
Problem is - contacts.organization is frequently empty, and I get contacts like "John Smith ()". Is there a way to only concatenate the organization if it's non-empty?
Use a CASE statement
SELECT
records.id,
CASE contacts.organization
WHEN '' THEN contacts.name
ELSE contacts.name + ' (' + contacts.organization + ')'
END as Contact
FROM records
LEFT JOIN contacts ON records.contact = contacts.contactid
You could modify it to also check for NULL values, but I do not believe you have that issue because if you had a NULL in your contacts.organization, your entire result field would be null instead of blank.
Not sure if this is the best way to do it:
CASE contacts.organization
WHEN '' THEN ''
ELSE '(' + contacts.organzation + ')' END
use a CASE, like CASE WHEN contacts.organization not null then ' (' + c.o + ') ' else '' end
You always need to expect nulls, because of your outer join:
select
records.id,
contacts.name + CASE WHEN contacts.organization IS NULL OR contacts.organization='' THEN '' ELSE ' (' + contacts.organization + ')' END as contact,
from records
left join contacts on records.contact = contacts.contactid
If you're dealing with NULL values there are some functions that specialize in them which are worth knowing.
ISNULL()
COALESCE()
NULLIF()
NULLIF() might be the one you're looking for. It basically takes two params. It returns the first param unless it is NULL, otherwise it returns the second.
Here's what I approximate your code would be:
select
records.id,
contacts.name + ISNULL(' (' + contacts.organization + ')', '') as contact,
from records
left join contacts on records.contact = contacts.contactid
Most NULL-related functions can be replaced by a larger CASE statement. CASE is your more general tool. But using specific functions will make your code cleaner, or at least more terse.