T-SQL: Conversion failed when converting date and/or time from character string - tsql

Below is a trigger used to capture updates/inserts on an SQL table. I cannot figure out why, but whenever an update is done, I get the error message Conversion failed when converting date and/or time from character string. Here is the structure of the Transaction Log table:
CREATE TABLE [dbo].[TransactionLog](
[Id] [int] IDENTITY(1,1) NOT NULL,
[TransactionDate] [datetime] NOT NULL,
[Operator] [varchar](35) NOT NULL,
[TableName] [varchar](50) NOT NULL,
[Action] [char](1) NOT NULL,
[TableString] [nvarchar](255) NOT NULL,
[UserId] [char](6) NULL,
CONSTRAINT [PK_TransactionLog] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
Here is the table being updated:
CREATE TABLE [dbo].[AgentContEd](
[Id] [int] IDENTITY(1,1) NOT NULL,
[sNumber] [int] NOT NULL,
[StateCode] [char](3) NOT NULL,
[CourseCode] [char](6) NOT NULL,
[DateTaken] [date] NOT NULL,
[ExpirationDate] [date] NULL,
[CourseHours] [smallint] NOT NULL,
[Method] [varchar](15) NULL,
[LastChangeOperator] [char](8) NOT NULL,
[LastChangeDate] [datetime] NOT NULL,
[ControlId] [int] NULL,
CONSTRAINT [PK_AgentContEd] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
And here is the trigger that's causing the headache...
BEGIN
INSERT INTO dbo.TransactionLog
(
TransactionDate,
Operator,
TableName,
Action,
TableString,
UserId
)
SELECT
LastChangeDate,
'Op',
#tableName,
#action,
CAST(
'ID:' + CAST(ISNULL(Id, 'NULL') as char(4))
+ ' SymNum:' + CAST(ISNULL(sNumber, 'NULL') as char(10))
+ ' StateCode:' + ISNULL(StateCode, 'NULL')
+ ' DateTaken:' + CAST(ISNULL(DateTaken, 'NULL') as nvarchar(9))
+ ' ExpDate:' + CAST(ISNULL(ExpirationDate, 'NULL') as nvarchar(9))
+ ' CourseCode:' + ISNULL(CourseCode, 'NULL')
+ ' Hours:' + CAST(ISNULL(CourseHours, 'NULL') as char(3))
+ ' Mthd:' + ISNULL(Method, 'NULL')
As char(255)),
LastChangeOperator
FROM inserted
END

Try
+ ' DateTaken:' + ISNULL(CAST(DateTaken as varchar(9)), 'NULL')
+ ' ExpDate:' + ISNULL(CAST(ExpirationDate as varchar(9)), 'NULL')
I used varchar as it seems pointless to use nvarchar if you are going to be casting the string to char at the end anyway.
Also you probably need to use CONVERT with a style instead of CAST to store something useful. SELECT CAST(getdate() as nvarchar(9)) returns Sep 28 20 for me.
A list of formats is here

Related

SQL Server Wizard says my source datetime's are datetime2's. Process cannot be run

I am trying to export some records from ServerA.DatabaseA..Anchor to ServerB.DatabaseB..Anchor. The source is active. The destination is a development database. The destination has one additional field, a tenancy id.
SQL for Source table
CREATE TABLE [dbo].[Anchor](
[AnchorId] [int] IDENTITY(130,1) NOT NULL,
[NodeId] [int] NOT NULL,
[UnitName] [varchar](200) NOT NULL,
[SetPosition] [varchar](5) NOT NULL,
[CreateDate] [datetime] NOT NULL,
[StartDate] [datetime] NOT NULL,
[EndDate] [datetime] NOT NULL,
[Latitude] [float] NULL,
[Longitude] [float] NULL,
[RadiusMeters] [int] NOT NULL,
[Creator] [varchar](100) NULL,
[Cellnumber1] [varchar](20) NULL,
[Cellnumber2] [varchar](20) NULL,
[Cellnumber3] [varchar](20) NULL,
[EmailTo] [varchar](255) NULL,
[UseMsgFwdContacts] [bit] NOT NULL,
CONSTRAINT [PK_Anchor] PRIMARY KEY CLUSTERED
(
[AnchorId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Anchor] ADD CONSTRAINT [DF_Anchor_UseMsgFwdContacts] DEFAULT ((0)) FOR [UseMsgFwdContacts]
GO
SQL Query for selecting records
Datetime's are cast to datetime for testing
SELECT [AnchorId]
,'MXM' as OrgCode -- the new tenancy field
,[NodeId]
,[UnitName]
,[SetPosition]
,CAST([CreateDate] as DATETIME) as [CreateDate]
,CAST([StartDate] as DATETIME) as [StartDate]
,CAST([EndDate] as DATETIME) as [EndDate]
,[Latitude]
,[Longitude]
,[RadiusMeters]
,[Creator]
,[Cellnumber1]
,[Cellnumber2]
,[Cellnumber3]
,[EmailTo]
,[UseMsgFwdContacts]
FROM [client_Maxam].[dbo].[Anchor]
WHERE AnchorId >335
Click Ok and Next, and now...
Why is my source datatype being picked up as datetime2, preventing me from running the export.

SQL Server issue with SELECT and datetime2 [duplicate]

This question already has answers here:
SQL Server Query: Fast with Literal but Slow with Variable
(8 answers)
Closed 10 months ago.
I found a big difference of the query execution under MS SQL Server Standart 2019.
T-SQL
DECLARE #atTime datetime2 = '2022-05-04 13:23:20';
DECLARE #startTime datetime2;
DECLARE #shiftTime datetime2;
SET #startTime = #atTime;
SET #shiftTime = DATEADD(SECOND, -5, #atTime)
-- SELECT #shiftTime, #startTime
-- 2022-05-04 13:23:15.0000000 2022-05-04 13:23:20.0000000
-- #1 It takes 7 seconds to complete
SELECT TOP(1) * FROM [TrackerPositions] WITH(NOLOCK) WHERE AtTime BETWEEN #shiftTime AND #startTime
-- #1 It takes 0 seconds to complete
SELECT TOP(1) * FROM [TrackerPositions] WITH(NOLOCK) WHERE AtTime BETWEEN '2022-05-04 13:23:15.0000000' AND '2022-05-04 13:23:20.0000000'
Note: AtTime colum has datetime2
Please, help to get working fast SELECT #1
Thank you!
UPDATE #1
CREATE TABLE [dbo].[TrackerPositions](
[ID] [uniqueidentifier] NOT NULL,
[GPSTrackerID] [int] NOT NULL,
[AtTime] [datetime2](7) NOT NULL,
[Lat] [decimal](9, 6) NOT NULL,
[Lng] [decimal](9, 6) NOT NULL,
[GeoLocation] AS ([geography]::STGeomFromText(((('POINT('+CONVERT([varchar](20),[Lng],0))+' ')+CONVERT([varchar](20),[Lat],0))+')',(4326))),
[SignalLevel] [int] NULL,
[IPAddress] [nvarchar](40) NULL,
[Port] [int] NULL,
[Height] [int] NULL,
[IsMoving] [bit] NULL,
[Speed] [decimal](18, 4) NULL,
CONSTRAINT [PK_TrackerPositions] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 50, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[TrackerPositions] ADD CONSTRAINT [DF_TrackerPositions_ID] DEFAULT (newid()) FOR [ID]
GO
ALTER TABLE [dbo].[TrackerPositions] ADD CONSTRAINT [DF_TrackerPositions_IsMoving] DEFAULT ((0)) FOR [IsMoving]
GO
ALTER TABLE [dbo].[TrackerPositions] WITH CHECK ADD CONSTRAINT [FK_TrackerPositions_GPSTrackers] FOREIGN KEY([GPSTrackerID])
REFERENCES [dbo].[GPSTrackers] ([ID])
GO
ALTER TABLE [dbo].[TrackerPositions] CHECK CONSTRAINT [FK_TrackerPositions_GPSTrackers]
GO
The right answer is to use OPTION(RECOMPILE)
SELECT TOP(1) * FROM [TrackerPositions] WITH(NOLOCK) WHERE AtTime BETWEEN #shiftTime AND #startTime OPTION(RECOMPILE)

Ordering contents of T-SQL STRING_AGG() [duplicate]

I have this query (I am using SQL Server 2019) and is working fine (combining Dates and Notes into one column). However, the result I am looking for is to have the latest date show up first.
How can I achieve that from this query?
SELECT ID,
​(SELECT string_agg(​concat(Date, ': ', Notes), CHAR(13) + CHAR(10) + CHAR(13) + CHAR (10)) as Expr1​
FROM(SELECT DISTINCT nd.Notes, nd.Date
FROM dbo.ReleaseTrackerNotes AS nd
INNER JOIN dbo.ReleaseTracker AS ac4 ON ac4.ID = nd.ReleaseTrackerID
WHERE (ac4.ID = ac.ID)) AS z_1) AS vNotes
FROM dbo.ReleaseTracker AS ac
GROUP BY ID
I have tried the ORDER BY but is not working
Here is my table:
CREATE TABLE [dbo].[ReleaseTrackerNotes](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ReleaseTrackerID] [int] NULL,
[AOC_ModelID] [int] NULL,
[Date] [date] NULL,
[Notes] [nvarchar](800) NULL,
CONSTRAINT [PK_ReleaseTrackerNotes] PRIMARY KEY CLUSTERED
CREATE TABLE [dbo].[ReleaseTracker](
[ID] [int] IDENTITY(1,1) NOT NULL,
[AOC_ModelID] [int] NOT NULL,
[MotherboardID] [int] NOT NULL,
[StatusID] [int] NOT NULL,
[TestCateoryID] [int] NULL,
[TestTypeID] [int] NULL,
[DateStarted] [date] NULL,
[DateCompleted] [date] NULL,
[LCS#/ORS#] [nvarchar](20) NULL,
[ETCDate] [date] NULL,
[CardsNeeded] [nvarchar](2) NULL,
CONSTRAINT [PK_Compatibility] PRIMARY KEY CLUSTERED
Use WITHIN GROUP (ORDER BY ...):
SELECT
ID,
STRING_AGG(​TRY_CONVERT(varchar, Date, 101) + ': ' + Notes +
CHAR(13) + CHAR(10) + CHAR(13), CHAR(10))
WITHIN GROUP (ORDER BY Date DESC) AS Expr1​
FROM
(
SELECT DISTINCT ac4.ID, nd.Notes, nd.Date
FROM dbo.ReleaseTrackerNotes AS nd
INNER JOIN dbo.ReleaseTracker AS ac4
ON ac4.ID = nd.ReleaseTrackerID
) AS vNotes
GROUP BY ID;

in T-SQL, is it possible to find names of columns containing NULL in a given row (without knowing all column names)?

Is it possible in T-SQL to write a proper query reflecting this pseudo-code:
SELECT {primary_key}, {column_name}
FROM {table}
WHERE {any column_name value} is NULL
i.e. without referencing each column-name explicitly.
Sounds simple enough but I've searched pretty extensively and found nothing.
You have to use dynamic sql to solve that problem. I have demonstrated how it could be done.
With this sql you can pick a table and check the row with id = 1 for columns being null and primary keys. I included a test table at the bottom of the script. Code will not display anything if there is not primary keys and no columns being null.
DECLARE #table_name VARCHAR(20)
DECLARE #chosencolumn VARCHAR(20)
DECLARE #sqlstring VARCHAR(MAX)
DECLARE #sqlstring2 varchar(100)
DECLARE #text VARCHAR(8000)
DECLARE #t TABLE (col1 VARCHAR(30), dummy INT)
SET #table_name = 'test_table' -- replace with your tablename if you want
SET #chosencolumn = 'ID=1' -- replace with criteria for selected row
SELECT #sqlstring = COALESCE(#sqlstring, '') + 'UNION ALL SELECT '',''''NULL '''' '' + '''+t1.column_name+''', 1000 ordinal_position FROM ['+#table_name+'] WHERE [' +t1.column_name+ '] is null and ' +#chosencolumn+ ' '
FROM INFORMATION_SCHEMA.COLUMNS t1
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE t2
ON t1.column_name = t2.column_name
AND t1.table_name = t2.table_name
AND t1.table_schema = t2.table_schema
WHERE t1.table_name = #table_name
AND t2.column_name is null
SET #sqlstring = stuff('UNION ALL SELECT '',''''PRIMARY KEY'''' ''+ column_name + '' '' col1, ordinal_position
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE table_name = ''' + #table_name+ '''' + #sqlstring, 1, 10, '') + 'order by 2'
INSERT #t
EXEC( #sqlstring)
SELECT #text = COALESCE(#text, '') + col1
FROM #t
SET #sqlstring2 ='select '+stuff(#text,1,1,'')
EXEC( #sqlstring2)
Result:
id host_id date col1
PRIMARY KEY PRIMARY KEY PRIMARY KEY NULL
Test table
CREATE TABLE [dbo].[test_table](
[id] int not null,
[host_id] [int] NOT NULL,
[date] [datetime] NOT NULL,
[col1] [varchar](20) NULL,
[col2] [varchar](20) NULL,
CONSTRAINT [PK_test_table] PRIMARY KEY CLUSTERED
(
[id] ASC,
[host_id] ASC,
[date] ASC
))
Test data
INSERT test_table VALUES (1, 1, getdate(), null, 'somevalue')

T-SQL Generate Unique Codes

I have a table contacts.
CREATE TABLE [dbo].[Contacts](
[ContactId] [int] IDENTITY(1,1) NOT NULL,
[ContactCode] [nvarchar](10) NOT NULL, --UNIQUE
[FirstName] [nvarchar](24) NOT NULL,
[MiddleName] [nvarchar](12) NULL,
[LastName] [nvarchar](24) NOT NULL,
CONSTRAINT [PK_Contacts] PRIMARY KEY CLUSTERED
(
[ContactId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
I would like to be able to generate a 10-digit contact code from the stored procedure which should comprise of
First Two Digits of FirstName
First Digit of MiddleName(When MiddleName is not blank)
First Two or Three(When MiddleName is Blank) Digits of Last Name
Four digit number starting from zero.
Example.
John M. Denver = JOMDE-0001
John Denver = JODEN-0001
John Denver = JODEN-0002
Bob Dylan = BODYL-0001
Proposed solution could be a function which could be called from inside the stored procedure before saving the values to the table.
CREATE FUNCTION GetContactCode
(
#FirstName nvarchar(24),
#MiddleName nvarchar(12),
#LastName nvarchar(24)
)
RETURNS nvarchar(10)
AS
BEGIN
RETURN('CODE')
END
Can anybody help?
Using a RANKING clause is one option.
;WITH q AS (
SELECT ContactID
, ContactCode =
UPPER(
SUBSTRING(
SUBSTRING(FirstName, 1, 2)
+ ISNULL(SUBSTRING(MiddleName, 1, 1), '')
+ SUBSTRING(LastName, 1, 3)
, 1, 5)
+ '-')
FROM Contacts
)
SELECT c.*
, q.ContactCode
+ RIGHT(REPLICATE('0', 4)
+ CAST(
RANK() OVER (PARTITION BY q.ContactCode ORDER BY q.ContactID
) AS VARCHAR(4))
, 4)
FROM q INNER JOIN Contacts c ON c.ContactId = q.ContactID
This function should do the trick
CREATE FUNCTION GetContactCode
(
#FirstName nvarchar(24),
#MiddleName nvarchar(12),
#LastName nvarchar(24)
)
RETURNS nchar(10)
AS
BEGIN
declare #contactcode nchar(10)
select top 1 #contactcode = contactCode
from contacts
where
contactcode like left(#FirstName,2)+
case
when #MiddleName is null or #MiddleName = '' then left(#LastName,3)
else left(#MiddleName,1)+left(#LastName,2)
end+'%'
order by contactCode desc
select #Contactcode =
Upper(left(#FirstName,2)+
case
when #MiddleName is null or #MiddleName = '' then left(#LastName,3)
else left(#MiddleName,1)+left(#LastName,2)
end) + '-' +
case
when #ContactCode is null then'0001'
else replace(str(cast(right(#ContactCode,4) as int)+1,4),' ','0')
end
Return #ContactCode
END