Ambiguity in Select Query - sql

This is my test table:
CREATE TABLE [General].[Test]
(
[Name] NVARCHAR(20) NOT NULL,
[SSN] CHAR(10) NOT NULL,
CONSTRAINT [UK_Test_SSN]
UNIQUE NONCLUSTERED ([SSN]) WITH (IGNORE_DUP_KEY = OFF),
)
And I inserted some values:
INSERT INTO [General].[Test] ([SSN], [Name]) VALUES (N'901223476', N'Lol1');
INSERT INTO [General].[Test] ([SSN], [Name]) VALUES (N'2591830061', N'Lol2');
INSERT INTO [General].[Test] ([SSN], [Name]) VALUES (N'4431776273', N'Lol3');
INSERT INTO [General].[Test] ([SSN], [Name]) VALUES (N'987654321', N'Lol4');
INSERT INTO [General].[Test] ([SSN], [Name]) VALUES (N'123456789', N'Lol5');
INSERT INTO [General].[Test] ([SSN], [Name]) VALUES (N'0123456789', N'Lol6');
INSERT INTO [General].[Test] ([SSN], [Name]) VALUES (N'0012345678', N'Lol7');
INSERT INTO [General].[Test] ([SSN], [Name]) VALUES (N'123', N'Lol8');
And the first SELECT query:
SELECT
CASE
WHEN [T].[SSN] LIKE REPLICATE('[0-9]',10) THEN [T].[SSN]
ELSE 1000000000 + ROW_NUMBER() OVER(ORDER BY [T].[Name]) END AS [SSN]
FROM [General].[Test] AS [T];
GO
And the second query:
SELECT [T].[SSN] FROM [General].[Test] AS [T];
The ambiguity that I can't understand is about rows 6 and 7 whose [SSN] values start with 0
So for example about 6th row the first query returns 123456789 and second query return 0123456789, can anyone explain why? And I really need to get the real value of 0123456789 in the first query, what can I do?

You have two different datatypes being returned from your first column in the first query - in the first case, the CHAR(10) of the [SSN] is returned, in the ELSE case a large INT number. That's why SQL Server needs to convert one of the two datatypes to the other.
What you need to do, if you want to get back the CHAR(10), is to CAST the second expression to that datatype:
SELECT
CASE
WHEN [T].[SSN] LIKE REPLICATE('[0-9]', 10) THEN [T].[SSN]
ELSE CAST(1000000000 + ROW_NUMBER() OVER(ORDER BY [T].[Name]) AS CHAR(10))
END
FROM [General].[Test] AS [T];
Then you get back your CHAR(10) values - and nothing gets converted to a INT (or BIGINT) and thus looses it's leading zeroes:
(No column name)
1000000001
2591830061
4431776273
1000000004
1000000005
0123456789
0012345678
1000000008

Related

Continue insert if one row fails in SQL Server

I have a question about SQL Server - how to continue insert if one row fails?
I have two tables, emp and empref. I want insert rows into the empref table using emp table.
While inserting, one of the rows fails with an "unexpected format" error. emp and empref both have the same columns, but datatypes are different.
Source : emp
CREATE TABLE [dbo].[emp]
(
[id] [varchar](50) NULL,
[name] [varchar](50) NULL,
[sal] [int] NULL
)
INSERT INTO [dbo].[emp] ([id], [name], [sal]) VALUES (N'1', N'abc', 100)
INSERT INTO [dbo].[emp] ([id], [name], [sal]) VALUES (N'2', N'xyz', 200)
INSERT INTO [dbo].[emp] ([id], [name], [sal]) VALUES (N'a4', N'un', 300)
In the empref ref expected int value but one values alphanumeric values.
CREATE TABLE [dbo].[empref]
(
[id] [int] NULL,
[name] [varchar](50) NULL,
[sal] [int] NULL
)
Expected result in empref table :
id |name | name
---+-----+------
1 |abc | 100
2 |xyz | 200
I tried like this:
BEGIN TRY
INSERT INTO empref
SELECT * FROM emp
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() erro
END CATCH
This query is not returning the expected result.
Please tell me how to write the query to achieve this task in SQL Server
You can use TRY_CAST to check if the conversion will work
INSERT INTO empref
(id, name, sal)
SELECT
TRY_CAST(e.id AS int),
e.name,
e.sal
FROM emp e
WHERE TRY_CAST(e.id AS int) IS NOT NULL;
db<>fiddle
Note: Always specify columns to be inserted into.

How to insert into a table with a unique identity INT column as primary key

To insert into a table with the next integer ID value, would it look something like this?
DECLARE #RoomID INT
SELECT #RoomID = (SELECT count(*) FROM [dbo].[Rooms])
SELECT #RoomID = SELECT #RoomID + 1
INSERT INTO [dbo].[Rooms]
([RoomID],
[RoomType],
[Description],
[DateCreated],
[IsActive])
VALUES
(#RoomID,
2,
N'Room Description X',
CONVERT(DateTime2, getdate()),
1)
If you want to force a specific number into a column that is an identity column you have to use the command SET IDENTITY_INSERT table_name OFF and turn it back on after your done.
https://learn.microsoft.com/en-us/sql/t-sql/statements/set-identity-insert-transact-sql
If you just want to insert data into the table, you skip the column and SQL Server will insert it for you.
INSERT INTO [dbo].[Rooms]
(
[RoomType],
[Description],
[DateCreated],
[IsActive])
VALUES
(
2,
N'Room Description X',
CONVERT(DateTime2, getdate()),
1)

Merge not working for insert a record when it's doesn't exist

Can I use Merge to insert a record when it's doesn't exist like below,
MERGE INTO [dbo].[Test] AS [Target]
USING (SELECT DISTINCT [Name] FROM [dbo].[Test]) AS [Source]
ON [Target].[Name] = [Source].[Name]
WHEN NOT MATCHED THEN
INSERT ([Id], [Name])
VALUES (NEWID(), 'Hello');
If the record with value Hello does not exists in table Test, insert it otherwise don't do anything. With above code record is not inserted even I don't have this record in table. And there are no errors.
I know how to accomplish this using insert ... where not exists (...) but am specifically wanting to know how to do it using a merge statement.
The reason your merge statement wasn't working is that you were merging the same table, dbo.Test, back onto itself, so of course there is no missing record.
You can insert a single missing record as follows, where you create a source query to contain the record(s) you wish to insert:
declare #Test table (id uniqueidentifier, [Name] nvarchar(64))
select * from #Test
-- Returns
-- id | Name
-- ----------------------------------------------
MERGE INTO #Test AS [Target]
USING (select 'Hello' [Name]) AS [Source]
ON [Target].[Name] = [Source].[Name]
WHEN NOT MATCHED THEN
INSERT ([Id], [Name])
VALUES (NEWID(), [Name]);
select * from #Test
-- Returns
-- id | Name
-- ----------------------------------------------
-- C1C87CD5-F745-436D-BD8D-55B2AF431BED | Hello
I agree with the answer from Dale K. Its correct.
If I suppose you might have a source_table from where the data needs to get inserted and not to get inserted if the record already exists then you can do the following.
Instead of the MERGE you can
insert
into dbo.Test
(id
,name
)
select top 1
newID()
,'Hello'
from dbo.Test a
where not exists(select 1
from dbo.Test b
where b.name='Hello')

Can a Pivot table be used with a unknown number of columns?

If I have a team table with a unknown amount of members, is there a way to make the pivot query dynamic?
create table #t (
team varchar (20), member varchar (20)
)
insert into #t values ('ERP', 'Jack')
insert into #t values ('ERP', 'John')
insert into #t values ('ERP', 'Mary')
insert into #t values ('ERP', 'Tim')
insert into #t values ('CRM', 'Robert')
insert into #t values ('CRM', 'Diana')
select * from #t
select team, [1] as teamMember1, /* 1st select */
[2] as teamMember2, [3] as teamMember3
from
(select team , member, row_number () /* 3rd select */
over (partition by team order by team) as rownum
from #t) a
pivot (max(member) for rownum in ([1], [2], [3])) as pvt
drop table #t
Why yes, yes there is. Here's a script I cooked up years ago for a similar problem that was ultimately solved by giving the user Excel and washing my hands of it. I apologize it's not configured with your example data, but hopefully it's easy to follow.
Hope that helps,
John
--------------START QUERY--------------
-- Example Table
CREATE TABLE #glbTestTable
(
ProviderID INT,
Total INT,
PaymentDate SMALLDATETIME
)
--So the dates insert properly
SET DATEFORMAT dmy
-- Populate Example Table
INSERT INTO #glbTestTable VALUES (232, 12200, '12/01/09')
INSERT INTO #glbTestTable VALUES (456, 10200, '12/01/09')
INSERT INTO #glbTestTable VALUES (563, 11899, '02/03/09')
INSERT INTO #glbTestTable VALUES (221, 5239, '13/04/09')
INSERT INTO #glbTestTable VALUES (987, 7899, '02/03/09')
INSERT INTO #glbTestTable VALUES (1, 1234, '02/08/09')
INSERT INTO #glbTestTable VALUES (2, 4321, '02/07/09')
INSERT INTO #glbTestTable VALUES (3, 5555, '02/06/09')
-- Raw Output
SELECT *
FROM #glbTestTable
-- Build Query for Pivot --
DECLARE #pvtColumns VARCHAR(MAX)
SET #pvtColumns = ''
-- Grab up to the first 1023 "Columns" that we want to use in Pivot Table.
-- Tables can only have 1024 columns at a maximum
SELECT TOP 1023 #pvtColumns = #pvtColumns + '[' + CONVERT(VARCHAR, PaymentDate, 103) + '], '
FROM (SELECT DISTINCT PaymentDate FROM #glbTestTable) t_distFP
-- Create PivotTable Query
DECLARE #myQuery VARCHAR(MAX)
SET #myQuery = '
SELECT ProviderID, ' + LEFT(#pvtColumns, LEN(#pvtColumns) - 1) + '
FROM (SELECT ProviderID, PaymentDate, Total
FROM #glbTestTable) AS SourceTable
PIVOT
(
SUM(Total)
FOR PaymentDate IN (' + LEFT(#pvtColumns, LEN(#pvtColumns) - 1) + ')
) AS PivotTable'
-- Run the Pivot Query
EXEC(#myQuery)
-- Cleanup
DROP TABLE #glbTestTable
---------------END QUERY---------------

INSERT INTO With a SubQuery and some operations

I'm trying to insert some data to a table contains two things : "a string" and "maximum number in Order column + 1".
This is my query:
INSERT INTO MyTable ([Text],[Order])
SELECT 'MyText' , (Max([Order]) + 1)
FROM MyTable
What is going wrong with my query?
I'm using Microsoft SQL Server 2005 SP3.
You can test this query like this:
I don't receive error:
create table #MyTable
(
[Text] varchar(40),
[Order] int NOT NULL
)
INSERT INTO #MyTable([Text],[Order])
SELECT 'MyText' [Text], isnull(max([order]) + 1, 0) [Order]
FROM #MyTable
drop table #MyTable
Original:
INSERT INTO MyTable ([Text],[Order])
SELECT 'MyText' [Text], max([Order]) + 1 [Order]
FROM MyTable
or
INSERT INTO MyTable ([Text],[Order])
SELECT top 1 'MyText' [Text], max([Order]) + 1 [Order]
FROM MyTable
limit is not valid in SQL Server as far as I know.
Cannot insert the value NULL into column 'Order', table 'master.dbo.MyTable'; column does not allow nulls. INSERT fails. The statement has been terminated.
This means that the Order column isn't allowed to be null, and that the Max([Order]) + 1 part of your column returns NULL.
This is because your table is empty, as you already noticed by yourself.
You can work around this by replacing NULL by a real number in the query, using ISNULL():
INSERT INTO MyTable ([Text],[Order])
SELECT 'MyText' , (isnull(Max([Order]),0) + 1)
FROM MyTable
Unless he has a column named OrderBy
then he would have to add / assign all values within that Insert especially if the column does not allow for nulls
sounds like fully qualifying the Insert with the dbo.MyTable.Field may make more sense.
also why are you naming fields with SQL Key words...???
INSERT INTO MyTable ([Text],[Order] Values('MyTextTest',1)
try a test insert first..