I have an XML column in a table; I want to "promote" a certain value in that XML as a computed column and index it for faster searching. I have a function that takes in the XML information and outputs the element of interest, like this:
CREATE FUNCTION [dbo].[fComputeValue] (#data XML)
RETURNS datetime
WITH SCHEMABINDING
AS
BEGIN
RETURN #data.value('(/Metadata/Value[#Key="StartDate"])[1]', 'datetime')
END
However when I try to create the computed column:
ALTER TABLE dbo.CustomMetadataTable ADD [StartDate] AS ([dbo].[fComputeValue]([CustomMetadataColumn])) PERSISTED
I get the following error:
Msg 4936, Level 16, State 1, Line 2
Computed column
'StartDate'
in table 'CustomMetadataTable' cannot be
persisted because the column is
non-deterministic.
It works if I:
work with varchar, int, double (i.e. other than datetime) values
remove the PERSISTED keyword (but then I can't create an index on the column)
I should also mention that datetime values are in XSD datetime format.
Any ideas? Thanks.
What about:
CREATE FUNCTION [dbo].[fComputeValue] (#data XML)
RETURNS varchar(50)
WITH SCHEMABINDING
AS
BEGIN
RETURN #data.value('(/Metadata/Value[#Key="StartDate"])[1]', 'varchar(50)')
END
and:
ALTER TABLE dbo.CustomMetadataTable ADD [StartDate] AS (convert(datetime,([dbo].[fComputeValue]([CustomMetadataColumn]), 127)) PERSISTED
or:
return convert(datetime, #data.value('(/Metadata/Value[#Key="StartDate"])[1]', 'varchar(50)'), 127)
From books online:
CONVERT is Deterministic unless one
of these conditions exists:
Source type is sql_variant.
Target type is sql_variant and its
source type is nondeterministic.
Source or target type is datetime or
smalldatetime, the other source or
target type is a character string, and
a nondeterministic style is specified.
To be deterministic, the style
parameter must be a constant.
Additionally, styles less than or
equal to 100 are nondeterministic,
except for styles 20 and 21. Styles
greater than 100 are deterministic,
except for styles 106, 107, 109 and
113.
It might help if you use CONVERT with style 127
Related
I am executing an ETL process and getting captioned error:
source datatype is char(1) and destination datatype is nchar(2)
How do I insert data from char to nchar?
Please help.
You don't say what platform you are using but you need to tell it to convert. Something like
SELECT CAST(GOVTPROGYN as NCHAR(2)) FROM TABLENAME_YOU_DID_NOT_SAY
or
SELECT CAST(GOVTPROGYN as CHAR(1)) FROM TABLENAME_YOU_DID_NOT_SAY
Per your title error, the n in nchar adds support for unicode, (same with nvarchar vs varchar). The data you are trying to insert is type char, but your destination field (GovtProgYN?) requires nchar.
Most SQL engines support a CAST function, which looks something like this: CAST( field AS datatype ). In your case, you would want to cast your insert value to nchar(2).
Example:
INSERT INTO Table ( GovtProgYN )
VALUES ( CAST ( #value AS nchar(2) )
Some SQL engines, like SQL Server, require you to designate unicode using the N prefix to a character string. If you are trying to manually insert a nchar value, use N'c' rather than 'c'.
Example:
INSERT INTO Table ( GovtProgYN )
VALUES ( N'c' )
ALTER TABLE table_name
ALTER COLUMN columnWithDate datetime;
columnWithDate is a type of nvarchar(255), data are in 2018.06.19. form. I've checked all distinct values and there are one row with NULL value in columnWithDate.
I get the following error runninf the alter command:
The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value.
What am I missing here?
You need to first change your values to a unambiguous format and then change the datatype. For the value you have that would be simply removing the ., as that produces the ISO format yyyyMMdd:
UPDATE YourTable
SET YourDateColumn = REPLACE(YourDateColumn,'.','');
ALTER TABLE YourTable ALTER COLUMN YourDateColumn datetime; --Should this not be a date?
As I comment though, date would likely be a better choice here, as you have no time portion in your value(s).
I suspect the extra dot(.) after the date is the culprit. In your example 2018.06.19.
This below snippet giving me the same error
DECLARE #DATE NVARCHAR(255)= N'2018.06.19.'
SELECT CAST(#DATE AS datetime)
Msg 242, Level 16, State 3, Line 3 The conversion of a nvarchar data
type to a datetime data type resulted in an out-of-range value.
So just remove the dot from the nvarchar field befor Alter.
The value is not correct somewhere in the column. I would suggest finding it:
select columnWithDate
from table_name
where try_convert(datetime, columnWithDate) is null and
columnWithDate is not null;
If you want to remove incorrect dates, then update first:
update table_name
set columnWithDate = try_convert(datetime, columnWithDate);
This converts the value back to a string, but the string should be convertible on your system right back to a datetime.
I have this SQL statement to create a table that stores the JSON string data and the event time found in that JSON string.
CREATE TABLE [dbo].[EventLog]
(
[EventID] INT NOT NULL IDENTITY(1,1),
[EventTime] AS CAST(JSON_VALUE(RawEvent, '$.EventTime') AS DATETIME ) PERSISTED,
[RawEvent] NVARCHAR(MAX) NOT NULL
)
However I get the following error below when I run this, I assume SQL Server does not know if the value fits DATETIME? is there a way to get this column defined?
Msg 4936, Level 16, State 1, Line 26
Computed column 'EventTime' in table 'Event' cannot be persisted because the column is non-deterministic.
You can use CONVERT with dates and have deterministic behavior as long as you specify certain date styles. As per the docs here, with the most common JavaScript date formats (since you are converting from JSON), you can use style 126 or 127, which are ISO8601 and ISO8601 with time zone. Your table, then, could be specified like this:
CREATE TABLE [dbo].[EventLog]
(
[EventID] INT NOT NULL IDENTITY(1,1),
[EventTime] AS CONVERT(DATETIME, JSON_VALUE(RawEvent, '$.EventTime'), 126) PERSISTED,
[RawEvent] NVARCHAR(MAX) NOT NULL
)
Alas, this is explained in the documentation:
CAST Deterministic unless used with datetime, smalldatetime, or sql_variant.
You may be able to parse the date and reconstruct the value using datefromparts() or datetimefromparts().
I have a column datedocumented in the format YYYYMMDD and of the datatype nvarchar. I want to change the data type to datetime and update the column name exdatedocumented and alter the table using ALTER .can anyone help in this.I have tried something like this
update dbo.table2
set [DateDocumented] = convert(datetime,CAST([DateDocumented] as datetime),130)
I ended up getting error
Msg 242, Level 16, State 3, Line 1
The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value.
The statement has been terminated
.
You should be able to just change the column type:
alter dbo.table2 alter column DateDocumented datetime;
Your column is in a format suitable for conversion. If you wanted to use default formats instead, just do:
update table dbo.table2
set [DateDocumented] = convert(datetime, CAST([DateDocumented] as datetime));
This should also allow the column to be converted to a datetime.
1st change that column name then alter table
sp_RENAME 'dbo.table2.datedocumented', 'exdatedocumented' , 'COLUMN'
go
ALTER TABLE dbo.table2
ALTER COLUMN exdatedocumented datetime;
It seems we have two things going on here. Changing the type for a column. And changing the name for a column. Let's try to keep these separate so not to confuse things. I will adress the changing of type (from varchar to datetime):
First of all: Why datetime? Why note datetime2 (with whatever fractions of seconds you want, for instance datetime2(0))? The new types for date and time has been around for 10 years now!
Anyhow, you apparently have values in your table which are not valid dates! First thing you need to do is to find those rows and handle them. Lets say that you will change to datetime2(0), if not, then just change below to datetime instead:
SELECT *
FROM dbo.Table2
WHERE TRY_CAST(DateDocumented AS datetime2(0)) IS NULL
Select
cast(ltrim(rtrim(Substring(string,charindex('my',string)+len('my')+5,
charindex('for the company',string)-charindex('my',string)+len('my')-9))) as datetime)
from table
Select
cast(ltrim(rtrim(Substring(string,charindex('company',string)+len('company')+1,
len(String)-charindex('company',string)+len('company')-9)))as varchar)
from description
this 2 queries has a set of rows as output.
I want to insert these values to another table using single insert.
What i did is:
insert into table2(orderid,orderdate)
Select
cast(ltrim(rtrim(Substring(String, len('The order number')+1,
CHARINDEX ( 'as been created at', String) - len ('as been created at')))) as int)
,
cast(ltrim(rtrim(Substring(string,charindex('at',string)+len('at')+5,
charindex('for the company',string)-charindex('at',string)+len('at')-9))) as datetime)
from description
but its not inserted..its showing error like The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value..
Is there any another way to insert this?
when inserting a datetime you should specify a string that is SQL compliant i.e.
'YYYY-MM-DD HH:MM:SS'
I suspect that the CAST function cant convert the type specified. However you dont need to convert to a datetime, you can simply insert the string representation of the datetime.
Other issues you may encounter are the casting of ltrim(rtrim()) to an int. LTRIM, RTRIM both return a varchar. CHARINDEX already returns an int.
Ensure your types are consistent
To insert output from your two queries into a single table, the data types and number of columns from these queries should match with that of the table. You can use convert
CONVERT(
DATETIME,ltrim(rtrim(Substring(
string,charindex('at',string)+len('at')+5,
charindex('for the company',string)-charindex('at',string)+len('at')-9)))
,112)
for your datetime column and try (provided your target table has a datetime column for OrderDate).