Change NULL value to another value in SQL server - sql-server

I have 3 tables. ID and Name is the primary key for the first table.
First Table
ID | Name | Date
----------------
1 | AA | 11/02
2 | BB | 04/10
ID, Name and Option are the primary key for second table:
Second Table
ID | Name | Option | SeqNo
---------------------------
3 | DD | LOVE | 1
4 | EE | SINGLE | 1
Option is the primary key for the third table:
Third Table
Option | Status
---------------
LOVE | Y
MARRIED| Y
SINGLE | N
After I join these tables, I will get like this.
ID | Name | Option | SeqNo | Status
------------------------------------
1 | AA | NULL | NULL | NULL
2 | BB | NULL | NULL | NULL
3 | CC | LOVE | 1 | Y
4 | DD | SINGLE | 1 | N
My question is, how to change the NULL value to a value contain in another table?
As an example, The Option column must be filled in with the value inside the third table. I'm using SQL Server 2005

This link describes how to replace null values in different sql engines, including sql server -
http://www.sqlines.com/oracle/functions/nvl
Basically, the syntax you are looking for is -
ISNULL(SeqNo, 'N/A')

Related

How do I set 2 columns so each entry is unique against both columns?

I have a record that holds 2 license "keys" (actually GUIDs). When a request comes to our service it includes a key (GUID) in the request. I then do a query looking for a record that has this value in either the column Key1 or Key2.
The purpose of this is users will use Key1 for everything. Then they discover that Key1 has become public. So they switch to Key2 and then after 15 minutes, change the value of Key1. Now the old Key1 value is of no use.
By having the 2 keys, it allows the switch over with no downtime.
I need any key value to be unique. Not that any pair of values is unique. Not that a value in Key1 is unique in all rows for Key 1. But that a new value is unique in all rows.Key1 and rows.Key2.
Is there a way to force this in Sql Server. Or do I need to do this myself with a select before doing an insert or update?
-------------------------------------------------------------------------------------------
| LicenseId | ApiKey1 | APiKey2 |
| 1 | af53d192-7fa3-4be0-b3d4-7efe17a397b5 | 1a87cc4a-1941-4af7-aeaa-bf9690f47eef |
| 2 | 5bbc2d06-ed6f-4444-aa22-73820dd6f3f6 | c2bdd9d9-fd47-4727-83f8-02ed0e7537e1 |
| 3 | 8acfa8b4-aa4b-41a7-9d3d-b6ba1eac838e | 30c18f2d-5d89-4e5d-8e8e-2d2b647d6ab6 |
-------------------------------------------------------------------------------------------
I need to insure if I am going to create record LicenseId = 4, that if it has ApiKey2 = 'af53d192-7fa3-4be0-b3d4-7efe17a397b5', that the insert will fail because that guid is ApiKey1 for LicenseId = 1.
The most natural way to enforce this in the database is to put all keys in a single column. Eg
create table ApiKeys
(
LicenceId int,
KeyId int check (KeyId in (0,1)),
constraint pk_ApiKeys primary key (LicenceId,KeyId),
KeyGuid uniqueidentifier unique
)
Arguably having both the keys on the same row violates 1NF, and certainly your desire for uniqueness across the two column strongly suggests that they belong to a single domain.
So instead of storing ApiKey1 and ApiKey2 on the same row, you store them on two separate rows.
So instead of
---------------
| LicenseId | ApiKey1 | APiKey2 |
| 1 | af53d192-7fa3-4be0-b3d4-7efe17a397b5 | 1a87cc4a-1941-4af7-aeaa-bf9690f47eef |
| 2 | 5bbc2d06-ed6f-4444-aa22-73820dd6f3f6 | c2bdd9d9-fd47-4727-83f8-02ed0e7537e1 |
| 3 | 8acfa8b4-aa4b-41a7-9d3d-b6ba1eac838e | 30c18f2d-5d89-4e5d-8e8e-2d2b647d6ab6 |
-------------------------------------------------------------------------------------------
You would have:
----------------------------------------------------------
| LicenseId | KeyId | ApiKey |
| 1 | 0 | af53d192-7fa3-4be0-b3d4-7efe17a397b5|
| 1 | 1 | 1a87cc4a-1941-4af7-aeaa-bf9690f47ee4|
| 2 | 0 | 5bbc2d06-ed6f-4444-aa22-73820dd6f3f6|
| 2 | 1 | c2bdd9d9-fd47-4727-83f8-02ed0e7537e1|
| 3 | 0 | 8acfa8b4-aa4b-41a7-9d3d-b6ba1eac838e|
| 3 | 1 | 30c18f2d-5d89-4e5d-8e8e-2d2b647d6ab6|
----------------------------------------------------------

SQL Server TPH (Table Per Hierarchy) auto increment multiple columns base on type

We currently use TPT (Table Per Type) in Entity Framework, this is very slow as we have about 20 tables, when they are queried, Entity Framework creates some massive disguising SQL which is very slow.
Each table has an auto increment integer column, this allows each type to have a number that is incremented per type. This is what the clients wanted. Now that we are wanting to move to the more performant TPH, we need all these table columns moved to the one table.
How can we have the auto increment columns based on the type as in the results below?
e.g.
Current Job Task
| TaskId | TaskNumber |
-----------------------------
| 1234 | 1 |
| 2345 | 2 |
Current Work Task
| TaskId | TaskNumber |
-----------------------------
| 3244 | 1 |
| 3245 | 2 |
This is the TPH table structure we want, as you can see, we want the task number to increment based on the Type of task.
| TaskId | Type | JobTaskNumber | WorkTaskNumber |
---------------------------------------------------------------
| 1234 | Job | 1 | null |
| 2345 | Job | 2 | null |
| 3244 | Work | null | 1 |
| 3245 | Work | null | 2 |
I am wondering if we use a seeding table, but any solutions greatly appreciated
Many thanks
Andrew
OK so did what I thought would work.
Not a hugely nice approach as we need about 20 seed tables.Each table has just an identity id defined as a BIGINT in sql server
When we want to add and get a new incremented id we just call this using dapper to get the result.
INSERT INTO SeedMyTable DEFAULT VALUES; SELECT CAST(SCOPE_IDENTITY() AS BIGINT)

All caps word with lagging hyphen or plus doesn't match with CONTAINS in SQL Server 2008

When using a simple_termed CONTAINS statement on a fulltext column, I was very surprised to run across this behavioral discrepancy in SQL Server 2008 between all caps words and mixed/lowercase words with trailing hyphens - [or +, see end]. Consider this case:
CREATE TABLE has_hyphens (
id INT IDENTITY,
t VARCHAR(20)
);
CREATE FULLTEXT CATALOG ft_catalog AS DEFAULT;
ALTER TABLE has_hyphens ADD CONSTRAINT u_id UNIQUE NONCLUSTERED (id);
CREATE FULLTEXT INDEX ON has_hyphens(t) KEY INDEX u_id WITH STOPLIST=SYSTEM;
INSERT INTO has_hyphens(t) VALUES ('foo- bar'), ('FoO- bar'), ('FOO- bar');
The confusing part is with the following SELECT:
SELECT t FROM has_hyphens WHERE CONTAINS(t, 'foo');
/*
+----------+
| t |
+----------+
| foo- bar |
| FoO- bar |
+----------+
*/
which returns the rows with mixed- or lowercase foo, but not FOO- bar. Looking at the fulltext keywords:
SELECT * FROM sys.dm_fts_index_keywords_by_document(
DB_ID('sandbox'),
OBJECT_ID('has_hyphens')
);
/*
+--------------------+--------------+-----------+-------------+-----------------+
| keyword | display_term | column_id | document_id | occurence_count |
+--------------------+--------------+-----------+-------------+-----------------+
| 0x006200610072 | bar | 2 | 1 | 1 |
| 0x006200610072 | bar | 2 | 2 | 1 |
| 0x006200610072 | bar | 2 | 3 | 1 |
| 0x0066006F006F | foo | 2 | 1 | 1 |
| 0x0066006F006F | foo | 2 | 2 | 1 |
| 0x0066006F006F002D | foo- | 2 | 1 | 1 |
| 0x0066006F006F002D | foo- | 2 | 2 | 1 |
| 0x0066006F006F002D | foo- | 2 | 3 | 1 |
| 0xFF | END OF FILE | 2 | 1 | 1 |
| 0xFF | END OF FILE | 2 | 2 | 1 |
| 0xFF | END OF FILE | 2 | 3 | 1 |
+--------------------+--------------+-----------+-------------+-----------------+
*/
We see row 3 with FOO- bar doesn't have a foo term alone, only a foo- term with a trailing hyphen, which is why the exact match doesn't hit. Why is this?
I've tested all other ASCII word breakers for English, and + also inhibits matching. It is alone with hyphen though, none of the other 90 characters do.
This behavior appeared for me in SQL Server 2008 Express with Advanced Services, but I cannot reproduce this in SQL Server 2014 Enterprise, perhaps suggesting it's version dependent?
I tested with the query:
-- Helper table for generating ASCII characters
CREATE TABLE incr( id INT IDENTITY );
INSERT INTO incr VALUES (1), (2), (3), (4), (5), (6), (7), -- snip, to 255
-- reusing table despite now-inaccurate name
TRUNCATE TABLE has_hyphens;
INSERT INTO has_hyphens
SELECT 'FOO'+CHAR(AVG(id))+' bar' FROM incr
CROSS APPLY sys.dm_fts_parser('"word1'+CHAR(id)+'word2"', 1033, 0, 0) fts
WHERE id<>34 AND id<256
GROUP BY id
HAVING COUNT(fts.keyword)>1; -- generate all 'FOO'+[breaker character]+' bar'
-- combinations
SELECT * FROM has_hyphens WHERE NOT CONTAINS(t, 'FOO');

records exist or not based on conditions in sql server 2008

Hi I have doubt in sql server
Trantable:
empid | deptid | Projectname | Transactionid
1 |10 | test | 1
2 |11 | test1 | 2
2 |10 | jai | 3
2nd table: dimemp ....> here dimemp is scdtype2 dimension.its all ready done
empkey | empid | ename | flag
1 | 1 | a | 1
2 | 2 | b | 1
3 | -1 | na | 1
3rd table: dimdept------>here dimdept is scdtype2 dimension.implementaion allready done.
deptkey | deptid | deptname | flag
1 | 10 | hr | 1
2 | 11 | ceo | 1
3 | -1 | NA | 1
Here I want load trantable data into facttran table with corresponding keys. here transactionid is unique column
to identiy unique record.
Facttran table structure look like below and factran we need to maintain scd type1 data.
empkey | deptkey | projectname |transactionid
I tried like below query
merge into facttran target
using (select ISNULL(a.empkey, (select empkey from Dimemp where empid = -1)) empkey,ISNULL(b.deptkey, (select deptkey from dimdept where deptid = -1)) deptkey, c.projectname, c.transactionid
from trantable c
left join dimemp a on a.empid=c.empid and a.flag=1
left join dimdept b on b.deptid=c.deptid and b.flag=1)source
on target.transactionid=source.transactionid
when not matched
then insert ([deptkey],[empkey],[projectname],[transactionid])
values(source.deptkey,source.empkey,source.projectname,source.transactionid)
when matched
then update set target.empkey=source.empkey ,
target.deptkey=source.deptkey,
target.projectname=source.projectname,
target.transactionid=source.transactionid ;
then I got output like below
Table :facttran
empkey | deptkey | projectname |transactionid
1 | 1 | test | 1
2 | 2 | test1 | 2
2 | 1 | Jai | 3
upto now its working fine.
2nd day in my trantable few records updated and few records insert in sourc trantable.based on below table data I want update in facttable with corresponding key.
2nd table: dimemp ....> here dimemp is scdtype2 dimension
empkey | empid | ename | flag
1 | 10 | a | 0
2 | 11 | b | 1
3 | -1 | na | 1
4 | 10 | aaa | 1
3rd table: dimdept------>here dimdept is scdtype2 dimension.implementaion allready done.
deptkey | deptid | deptname | flag
1 | 10 | hr | 0
2 | 20 | ceo | 1
3 | -1 | NA | 1
4 | 10 |hrdept | 1
Trantable:
empid | deptid | Projectname | Transactionid
1 |11 | test | 1 ------record updated in source side here deptid changed from 10 to 11
1 |11 | test123 | 2 -------Here empid changed from empid 2 to 1 and projectname changed test1 to test123
2 |10 | jai | 3 ------here no records are not changed
1 |10 | cod | 4 ----------new rocrd is came
based on above trantable.I want facttran table data look like below.
Table :facttran
empkey | deptkey | projectname |transactionid
1 | 2 | test | 1
1 | 2 | test123 | 2
2 | 1 | Jai | 3
4 | 10 | cod | 4
when I ran 2nd time with same query.I am not able get to expected result.
here mainily source trantable related transactioni id is exist or not in facttran table .if not exist then we need to insert correspondig dimensionkeys with lates flaf=1
values.if we found transactionid exist in fact table then we need to updated existing dimension corresonding key.
suppose if we take transactionid=1 records here only chnaged deptid not empid that time we donot need update empid corresponding lates flag=1 corresondingkey
we need check exisig transaction id is updated each dimension need to check exist or not if not exist latest flag=1 related corresponding key.
if exist we donot need to updated that one.if new reocrds came then we need to insert with latest flag=1 corresponding keys in factran table.
please tell me how to write query to achive this task in sql server.

SQL Server - tricky query to update contact id using ROW_NUMBER to reference index value

A previous developer used an index rather than the actual contactID to reference which of the associated contacts are the primary contact. The index works well when the app gets the contacts and sets the primary contact in the list on the page, but try joining for a report! Not easy; so I want to update the main table with the actual contact ID to make for a simple join and to avoid this buggary.
In this particular case, I need to update tblInquiry with the claimantContactID and agentContactID. Those two fields I just created and defaulted to 0. However, the challenge is to use the claimantContactIndex and agentContactIndex values from tblInquiry, to get the respective nth row from tblContacts. The index is 0 based, so if the index value is 2, then get the ID of the 3rd contact, for example.
Also, claimantContactIndex and agentContactIndex can either be NULL or some number. If NULL, then assume the first contact (index 0).
I will also add that the contacts index cannot have an order by on it because the application relies upon the natural order when getting the contacts list (there is no order by in the stored procedure), and selects then the index accordingly.
DB Platform: SQL Server 2008 R2 Express Edition.
I have the following table structure:
tblInquiry
id | claimantID | agentID | claimantContactIndex | agentContactIndex | claimantContactID | agentContactID
--------------------------------
1 | 1001 | 2001 | 2 | 0 | 0 | 0
2 | 1002 | NULL | 0 | NULL | 0 | 0
tblClaimant
id | name | address | phone | email
--------------------------------
1001 | Widgets Inc. | 123 W. Main | 5550000 | widgets#here.com
1002 | Thingies LLC. | 456 W. Main | 5551111 | thingies#here.com
tblAgent
id | name | address | phone | email
--------------------------------
2001 | Simon Bros. | 789 W. Main | 5552222 | simon#here.com
tblContacts
id | claimantID | agentID | fn | ln | phone | email
--------------------------------
3001 | 1001 | NULL | John | Doe | 5553333 | john#here.com
3002 | 1001 | NULL | Fred | Flynn | 5554444 | fred#here.com
3003 | 1001 | NULL | Mike | Brown | 55555555 | mike#here.com
3004 | 1001 | NULL | Susan | Pierce | 5556666 | susan#here.com
3005 | NULL | 2001 | Jeff | Bridges | 5557777 | jeff#here.com
3006 | NULL | 2001 | Karry | Sinclair | 5558888 | Karry#here.com
3007 | NULL | 2001 | Steve | Green | 5559999 | steve#here.com
3008 | NULL | 2001 | Peter | White | 5550001 | peter#here.com
Update:
I have worked out the select part of this solution and I can now get the correct claimant contact info using ROW_NUMBER() and a JOIN. I will add more to get correct agent contact info. I also handled the case where an index is NULL. And ultimately I will work this out to update the inquiry table now that I have the right contactID.
SELECT
i.id inquiryID, i.claimantContactIndex, i.agentContactIndex, i.claimantContactID, i.agentContactID
,r.id contactID, r.claimantID, r.agentID
,r.*
FROM
(
SELECT ROW_NUMBER()
OVER (Partition by con.claimantid Order by (SELECT NULL)) AS RowNumber, *
FROM tblContacts con
) r
INNER JOIN
tblInquiry i on i.claimantid = r.claimantid and ((isnull(i.claimantContactIndex, 0) + 1 = r.RowNumber ))
WHERE
i.id in (1, 2, 3, 4, 5)
ORDER BY
i.id
This issue was resolved by doing the following:
As I posted above, using ROW_NUMBER() and (SELECT NULL()) along with an isnull to handle null values to get the correct contacts.
I selected the results into a temp table.
I then updated the inquiry table by joining it to the temp table.
dropped temp table
I had to do this in two passes, once for claimants, a second time for agents.
Thx #EricH for pointing me in the right direction.
You could do something like:
Using ideas from here:
https://msdn.microsoft.com/en-us/library/ms186734.aspx
SELECT
ROW_NUMBER() OVER (Order by Id) AS RowNumber,
claimantID, agentID, (etc...)
FROM
tblContacts
To get an index based resultset. I'd drop it into a temp table and select from that where RowNumber = Whatever index you want.

Resources