I have this portion of the query where I'm doing this.
FROM #Table2 WHERE Attribute = ISNULL('+#Attrb+', Attribute)) AS D
Obviously this isn't working for me as #Attr can bring in a string or can be empty. is there a better way to handle this?
What I need is, this a parameter that is passed to this stored procedure. There are two possible choices (or a third one is empty). I'm allowing the users to type it in. How would you tackle this?
Thanks.
FROM #Table2 ' + ISNULL('WHERE Attribute = ''' + NULLIF(#Attrb,'') + '''', '') + ') AS D
Example
CREATE TABLE #Table2 (Attribute VARCHAR(MAX))
INSERT INTO #Table2 VALUES
('Id'),('Class'),('Name')
DECLARE #Attrb VARCHAR(MAX),
#SQL VARCHAR(MAX)
--Attrb is NULL
SET #SQL = ' SELECT * FROM #Table2 ' + ISNULL('WHERE Attribute = ''' + NULLIF(#Attrb,'') + '''', '')
EXEC(#SQL)
/*Result
Attribute
---------
Id
Class
Name
*/
--Give Attrb a value
SET #Attrb = 'Class'
SET #SQL = ' SELECT * FROM #Table2 ' + ISNULL('WHERE Attribute = ''' + NULLIF(#Attrb,'') + '''', '')
EXEC(#SQL)
/*Result
Attribute
---------
Class
*/
You haven't indicated what version of SQL server you are using, but if you are using 2012 or later, you might want to check iif
Example for testing:
declare #Attrib varchar(20)
set #Attrib = NULL
select iif(#Attrib is null,'Null Result',#Attrib)
I am not sure what the string literals are doing in there. I am pretty sure you want something like this.
WHERE Attribute = ISNULL(#Attrb, Attribute)
Or if you are trying to deal with NULL or an empty string you can use NULLIF
WHERE Attribute = ISNULL(NULLIF(#Attrb, ''), Attribute)
--EDIT--
Modifying this to work with dynamic sql is pretty straight forward.
'WHERE Attribute = ISNULL(NULLIF(' + ISNULL(#Attrb, Attribute) + ', ''''), Attribute)'
Related
I'm creating a stored procedure where I have this openquery:
SELECT #MY_QUERY = 'SELECT * FROM OPENQUERY(HYPER_CONN, ''
SELECT COALESCE(SUM(QUANT_RIGA),0) FROM DDT_CLI_RIGHE WHERE DOC_RIGA_ID = ''''' + #THE_DDT + ''''' '')'
In the where clause I set this variable #THEDDT:
DECLARE #THE_DDT nvarchar(MAX) = (SELECT STRING_AGG(DOC_RIGA_ID,',') FROM ...
For example it will be like #THEDDT = test1,test2,test3
I want set this variable in my "where in" clause.
So in the openquery I'm trying to have something like this (but using the varaible):
WHERE DOC_RIGA_ID IN ('test1','test2','test3')
Is there a way to do this?
This is more of a stab in the dark, as we don't have all the information, however, as I mentioned, it seems all you need to do is change your DOC_RIGA_ID = {literal} clause to a DOC_RIGA_ID IN ({delimited List}) clause:
DECLARE #THE_DDT nvarchar(MAX) = (SELECT STRING_AGG(QUOTENAME(DOC_RIGA_ID,''''),',') --Assumes DOC_RIGA_ID can't have a value longer than 128 characters
FROM ...
SELECT #MY_QUERY = 'SELECT * FROM OPENQUERY(HYPER_CONN, ''
SELECT COALESCE(SUM(QUANT_RIGA),0) FROM DDT_CLI_RIGHE WHERE DOC_RIGA_ID IN (' + REPLACE(#THE_DDT,'''','''''') + ')'') OQ;';
This is, of course, untested as I have no way of testing this statement.
I want to get a list of comma separated customer names. The below code only returns the last name
DECLARE #vfirstname NVARCHAR(500), #vdelimiter NVARCHAR(1)
SET #vdelimiter=','
SELECT #vfirstname = FirstName + #vdelimiter
FROM dbo.Customer c
SET #vfirstname = LEFT(#vfirstname, LEN( #vfirstname ) - 1);
PRINT #vfirstname
I was able to fix it introducing the below statements (with help from google):
SET #vfirstname =''
SELECT #vfirstname = #vfirstname + FirstName + #vdelimiter
FROM dbo.Customer c
But I am unable to understand the need to do this , how does the select statement really work in this scenario?
This will do what you need without the substring function, the
Select ',' is your delimiter
The stuff function removes the first comma/delimiter from the list for you using the XML path
-- use stuff instead of substringb
Select STUFF((
SELECT ',' + FirstName
FROM dbo.Customer
FOR XML PATH('')
), 1, 1,'')
FROM dbo.Customer
-- if you want a space after comma, need to update the STUFF to be 1, 2
I have just completed the process of loading new tables with data. I'm currently trying to validate the data. The way I have designed my database there really shouldn't be any values anywhere that are NULL so i'm trying to find all rows with any NULL value.
Is there a quick and easy way to do this instead of writing a lengthy WHERE clause with OR statements checking each column?
UPDATE: A little more detail... NULL values are valid initially as sometimes the data is missing. It just helps me find out what data I need to hunt down elsewhere. Some of my tables have over 50 columns so writing out the whole WHERE clause is not convenient.
Write a query against Information_Schema.Columns (documentation) that outputs the SQL for your very long where clause.
Here's something to get you started:
select 'OR ([' + TABLE_NAME + '].[' + TABLE_SCHEMA + '].[' + COLUMN_NAME + '] IS NULL)'
from mydatabase.Information_Schema.Columns
order by TABLE_NAME, ORDINAL_POSITION
The short version answer, use SET CONCAT_NULL_YIELDS_NULL ON and bung the whole thing together as a string and check that for NULL (once). That way any null will propagate through to make the whole row comparison null.
Here's the silly sample code to demo the principal, up to you if you want to wrap that in an auto-generating schema script (to only check Nullable columns and do all the appropriate conversions). Efficient it ain't, but almost any way you cut it you will need to do a table scan anyway.
CREATE TABLE dbo.Example
(
PK INT PRIMARY KEY CLUSTERED IDENTITY(1,1),
A nchar(10) NULL,
B int NULL,
C nvarchar(50) NULL
) ON [PRIMARY]
GO
INSERT dbo.Example(A, B, C)
VALUES('Your Name', 1, 'Not blank'),
('My Name', 3, NULL),
('His Name', NULL, 'Not blank'),
(NULL, 5, 'It''s blank');
SET CONCAT_NULL_YIELDS_NULL ON
SELECT E.PK
FROM dbo.Example E
WHERE (E.A + CONVERT(VARCHAR(32), E.B) + E.C) IS NULL
SET CONCAT_NULL_YIELDS_NULL OFF
As mentioned in a comment, if you really expect columns to not be null, then put NOT NULL constraints on them. That said...
Here's a slightly different approach, using INFORMATION_SCHEMA:
DECLARE #sql NVARCHAR(max) = '';
SELECT #sql = #sql + 'UNION ALL SELECT ''' + cnull.TABLE_NAME + ''' as TableName, '''
+ cnull.COLUMN_NAME + ''' as NullColumnName, '''
+ pk.COLUMN_NAME + ''' as PkColumnName,' +
+ 'CAST(' + pk.COLUMN_NAME + ' AS VARCHAR(500)) as PkValue '
+ ' FROM ' + cnull.TABLE_SCHEMA + '.' + cnull.TABLE_NAME
+ ' WHERE ' +cnull.COLUMN_NAME + ' IS NULL '
FROM INFORMATION_SCHEMA.COLUMNS cnull
INNER JOIN (SELECT Col.Column_Name, col.TABLE_NAME, col.TABLE_SCHEMA
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab
INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col
ON Col.Constraint_Name = Tab.Constraint_Name AND Col.Table_Name = Tab.Table_Name
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY') pk
ON pk.TABLE_NAME = cnull.TABLE_NAME AND cnull.TABLE_SCHEMA = pk.TABLE_SCHEMA
WHERE cnull.IS_NULLABLE = 'YES'
set #sql = SUBSTRING(#sql, 11, LEN(#sql)) -- remove the initial 'UNION ALL '
exec(#sql)
Rather a huge where clause, this will tell you the primary key on the table where any field in that table is null. Note that I'm CASTing all primary key values to avoid operand clashes if you have some that are int/varchar/uniqueidentifier etc. If you have a PK that doesn't fit into a VARCHAR(500) you probably have other problems....
This would probably need some tweaking if you have any tables with composite primary keys - as it is, I'm pretty sure it would just output separate rows for each member of the key instead of concatenating them, and wouldn't necessarily group them together the way you'd want.
One other thought would be to just SELECT * from ever table and save the output to a format (Excel, plain text csv) you can easily search for the string NULL.
Please look at the below query..
select name as [Employee Name] from table name.
I want to generate [Employee Name] dynamically based on other column value.
Here is the sample table
s_dt dt01 dt02 dt03
2015-10-26
I want dt01 value to display as column name 26 and dt02 column value will be 26+1=27
I'm not sure if I understood you correctly. If I'am going into the wrong direction, please add comments to your question to make it more precise.
If you really want to create columns per sql you could try a variation of this script:
DECLARE #name NVARCHAR(MAX) = 'somename'
DECLARE #sql NVARCHAR(MAX) = 'ALTER TABLE aps.tbl_Fabrikkalender ADD '+#name+' nvarchar(10) NULL'
EXEC sys.sp_executesql #sql;
To retrieve the column name from another query insert the following between the above declares and fill the placeholders as needed:
SELECT #name = <some colum> FROM <some table> WHERE <some condition>
You would need to dynamically build the SQL as a string then execute it. Something like this...
DECLARE #s_dt INT
DECLARE #query NVARCHAR(MAX)
SET #s_dt = (SELECT DATEPART(dd, s_dt) FROM TableName WHERE 1 = 1)
SET #query = 'SELECT s_dt'
+ ', NULL as dt' + RIGHT('0' + CAST(#s_dt as VARCHAR), 2)
+ ', NULL as dt' + RIGHT('0' + CAST((#s_dt + 1) as VARCHAR), 2)
+ ', NULL as dt' + RIGHT('0' + CAST((#s_dt + 2) as VARCHAR), 2)
+ ', NULL as dt' + RIGHT('0' + CAST((#s_dt + 3) as VARCHAR), 2)
+ ' FROM TableName WHERE 1 = 1)
EXECUTE(#query)
You will need to replace WHERE 1 = 1 in two places above to select your data, also change TableName to the name of your table and it currently puts NULL as the dynamic column data, you probably want something else there.
To explain what it is doing:
SET #s_dt is selecting the date value from your table and returning only the day part as an INT.
SET #query is dynamically building your SELECT statement based on the day part (#s_dt).
Each line is taking #s_dt, adding 0, 1, 2, 3 etc, casting as VARCHAR, adding '0' to the left (so that it is at least 2 chars in length) then taking the right two chars (the '0' and RIGHT operation just ensure anything under 10 have a leading '0').
It is possible to do this using dynamic SQL, however I would also consider looking at the pivot operators to see if they can achieve what you are after a lot more efficiently.
https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
I am creating a computed column across fields of which some are potentially null.
The problem is that if any of those fields is null, the entire computed column will be null. I understand from the Microsoft documentation that this is expected and can be turned off via the setting SET CONCAT_NULL_YIELDS_NULL. However, there I don't want to change this default behavior because I don't know its implications on other parts of SQL Server.
Is there a way for me to just check if a column is null and only append its contents within the computed column formula if its not null?
You can use ISNULL(....)
SET #Concatenated = ISNULL(#Column1, '') + ISNULL(#Column2, '')
If the value of the column/expression is indeed NULL, then the second value specified (here: empty string) will be used instead.
From SQL Server 2012 this is all much easier with the CONCAT function.
It treats NULL as empty string
DECLARE #Column1 VARCHAR(50) = 'Foo',
#Column2 VARCHAR(50) = NULL,
#Column3 VARCHAR(50) = 'Bar';
SELECT CONCAT(#Column1,#Column2,#Column3); /*Returns FooBar*/
Use COALESCE. Instead of your_column use COALESCE(your_column, ''). This will return the empty string instead of NULL.
You can also use CASE - my code below checks for both null values and empty strings, and adds a seperator only if there is a value to follow:
SELECT OrganisationName,
'Address' =
CASE WHEN Addr1 IS NULL OR Addr1 = '' THEN '' ELSE Addr1 END +
CASE WHEN Addr2 IS NULL OR Addr2 = '' THEN '' ELSE ', ' + Addr2 END +
CASE WHEN Addr3 IS NULL OR Addr3 = '' THEN '' ELSE ', ' + Addr3 END +
CASE WHEN County IS NULL OR County = '' THEN '' ELSE ', ' + County END
FROM Organisations
Use
SET CONCAT_NULL_YIELDS_NULL OFF
and concatenation of null values to a string will not result in null.
Please note that this is a deprecated option, avoid using.
See the documentation for more details.
I just wanted to contribute this should someone be looking for help with adding separators between the strings, depending on whether a field is NULL or not.
So in the example of creating a one line address from separate fields
Address1, Address2, Address3, City, PostCode
in my case, I have the following Calculated Column which seems to be working as I want it:
case
when [Address1] IS NOT NULL
then ((( [Address1] +
isnull(', '+[Address2],'')) +
isnull(', '+[Address3],'')) +
isnull(', '+[City] ,'')) +
isnull(', '+[PostCode],'')
end
Hope that helps someone!
ISNULL(ColumnName, '')
I had a lot of trouble with this too. Couldn't get it working using the case examples above, but this does the job for me:
Replace(rtrim(ltrim(ISNULL(Flat_no, '') +
' ' + ISNULL(House_no, '') +
' ' + ISNULL(Street, '') +
' ' + ISNULL(Town, '') +
' ' + ISNULL(City, ''))),' ',' ')
Replace corrects the double spaces caused by concatenating single spaces with nothing between them. r/ltrim gets rid of any spaces at the ends.
In Sql Server:
insert into Table_Name(PersonName,PersonEmail) values(NULL,'xyz#xyz.com')
PersonName is varchar(50), NULL is not a string, because we are not passing with in single codes, so it treat as NULL.
Code Behind:
string name = (txtName.Text=="")? NULL : "'"+ txtName.Text +"'";
string email = txtEmail.Text;
insert into Table_Name(PersonName,PersonEmail) values(name,'"+email+"')
This example will help you to handle various types while creating insert statements
select
'insert into doc(Id, CDate, Str, Code, Price, Tag )' +
'values(' +
'''' + convert(nvarchar(50), Id) + ''',' -- uniqueidentifier
+ '''' + LEFT(CONVERT(VARCHAR, CDate, 120), 10) + ''',' -- date
+ '''' + Str+ ''',' -- string
+ '''' + convert(nvarchar(50), Code) + ''',' -- int
+ convert(nvarchar(50), Price) + ',' -- decimal
+ '''' + ISNULL(Tag, '''''') + '''' + ')' -- nullable string
from doc
where CDate> '2019-01-01 00:00:00.000'