HashBytes with datetime2 field - sql

I am creating a hash key using hashbytes on multiple columns to get performance gain which we are using right now in where clause.
alter table dbo.Table1
add HashKey AS CAST(hashbytes('MD5', PID+PNumber+CONVERT([varchar] (50),[DateStamp]) +CONVERT(VARCHAR(50), TransactionCount)+OCD+ONbr+TransactionID) AS VARBINARY(80)) PERSISTED
But one of the column in that is a datetime2 field which i am unable to add. While i was trying i am getting below error message
"Computed column 'HashKey' in table 'table1' cannot be persisted because the column is non-deterministic.".
From my research i found that datetime2 cannot be used as it is non-deterministic.
But i cannot change the format as i need to compare the value exactly as it is including all milliseconds.
Can anybody please give me a work around?.Any alternate solution will be appreciated.

I am not sure of implications..
But casting datetime to binary always gives new value.see below for Example..
select getdate(),cast(getdate()as binary)
2016-08-02 10:17:20.573 0x000000000000000000000000000000000000000000000000A65600A98EEC
2016-08-02 10:17:40.537 0x000000000000000000000000000000000000000000000000A65600A9A651
so try like..
select hashbytes('md5',cast(getdate()as binary))

Related

How to alter datatype of a column in BigQuery

I'm trying to change the datatype for a column in my bigquery table from INT64 to STRING with the condition it's not NULL.
When I type:
ALTER TABLE table_name ALTER COLUMN id STRING NOT NULL
I get an error
Syntax error: Expected keyword DROP or keyword SET but got identifier "STRING"
How should I resolve this?
It is unsupported to change a column's data type at the moment.
Take a look at the official documentation. It explains 2 ways to manually change a column's data type. For the record:
Using a SQL query: choose this option if you are more concerned about simplicity and ease of use, and you are less concerned about costs.
Recreating the table: choose this option if you are more concerned about costs, and you are less concerned about simplicity and ease of use.
Despite the fact that you have got the error due to not using SET:
ALTER TABLE table_name
ALTER COLUMN id SET DATA TYPE STRING
but anyway, unfortunately, it's not possible to alter from INT64 to STRING directly.
What you can do is create a new table using
CAST(id AS STRING) id

Modifying a column type with data, without deleting the data

I have a column which I believe has been declared wrongly. It contains data and I do not wish to lose the data.
I wish to change the definition from varchar(max) to varchar(an integer). I was under the impression I cannot just alter the column type?
Is the best method to create a temp column, "column2", transfer the data to this column, from the column with the problematic type, delete the problem column and then rename the temp column to the original problematic column?
If so, how do I copy the values from the problem column to the new column?
EDIT: For anyone with same problem, you can just use the ALTER statements.
As long as the data types are somewhat "related" - yes, you can absolutely do this.
You can change an INT to a BIGINT - the value range of the second type is larger, so you're not in danger of "losing" any data.
You can change a VARCHAR(50) to a VARCHAR(200) - again, types are compatible, size is getting bigger - no risk of truncating anything.
Basically, you just need
ALTER TABLE dbo.YourTable
ALTER COLUMN YourColumn VARCHAR(200) NULL
or whatever. As long as you don't have any string longer than those 200 characters, you'll be fine. Not sure what happens if you did have longer strings - either the conversion will fail with an error, or it will go ahead and tell you that some data might have been truncated. So I suggest you first try this on a copy of your data :-)
It gets a bit trickier if you need to change a VARCHAR to an INT or something like that - obviously, if you have column values that don't "fit" into the new type, the conversion will fail. But even using a separate "temporary" new column won't fix this - you need to deal with those "non-compatible" cases somehow (ignore them, leave NULL in there, set them to a default value - something).
Also, switching between VARCHAR and NVARCHAR can get tricky if you have e.g. non-Western European characters - you might lose certain entries upon conversion, since they can't be represented in the other format, or the "default" conversion from one type to the other doesn't work as expected.
Calculate the max data length store int that column of that table.
Select max(len(fieldname)) from tablename
Now you can decrease the size of that column up to result got in previous query.
ALTER TABLE dbo.YourTable
ALTER COLUMN YourColumn VARCHAR(200) NULL
According to the PostgreSQL docs, you can simply alter table
ALTER TABLE products ALTER COLUMN price TYPE numeric(10,2);
But here's the thing
This will succeed only if each existing entry in the column can be converted to the new type by an implicit cast. If a more complex conversion is needed, you can add a USING clause that specifies how to compute the new values from the old.
add a temp column2 with type varchar(NN), run update tbl set column2 = column, check if any error happens; if everything is fine, alter your original column, copy data back and remove column2.

SQL Convert statement

I need help with a SQL convert statement. I have NetQuanity (masterTable) which is a varchar(15) and I have another table with Purchase price (PO TABLE) which is money. When I try to multiply them in a SQL view is gives me the error:
If your field is a VARCHAR, you'll need to CAST to the appropriate data type prior to your operation. e.g.
CAST(myVarCharField as INT) * myIntField
Be forewarned however, if you attempt to CAST this field to a numeric data type and it's not numeric, you'll be in the same boat.
I would recommend using CAST over CONVERT in your example, for the following reason defined in this SO post:
Related: T-SQL Cast versus Convert
Maybe try using the CONVERT function? CONVERT(money,NetQuantity).
First of all you have a data definition problem.
The first thing is to eliminate any non-numeric entries in the master table.
SELECT whatever FROM masterTable WHERE ISNUMERIC(NetQuanity)=1
The next step is to include this as a sub-query in the calculation.
In this query use CONVERT or CAST to convert the valid quanities to integer.
i.e.
CONVERT(INT, NetQuantity)

Convert datatype of existing data from Char to DateTime with SQL

I am relatively new to SQL Server and I am trying to update the datatype of about 3000 records from a Char to Datetime so I can use the DATEDIFF function. I created a view that achieves the conversion but what I think I need to do is alter the data in the origin table.
SELECT
CONVERT(datetime, CONVERT(char(8), TRANS_ACCOUNTINGDATE_ALLCAMPAIGNS_2010_ALLPROCESSINGACCOUNTS_ALL))
FROM Accounting;
What I think I need to do is an alter table and iterate over each row performing the conversion. Trying to change the data type using the GUI is not working for me.
Any help would be appreciated.
Thanks
The datatype is an attribute of the COLUMN, not just of the data inside the column. You can't put datetime data into a char field - that's the purpose of data types!
You need to add a new field and run an UPDATE statement to populate it with your converted data. Then you can drop the original field and rename your new one to the original name.

How to prevent CAST errors on SSIS?

The question
Is it possible to ask SSIS to cast a value and return NULL in case the cast is not allowed instead of throwing an error ?
My environment
I'm using Visual Studio 2005 and Sql Server 2005 on Windows Server 2003.
The general context
Just in case you're curious, here is my use case. I have to store data coming from somewhere in a generic table (key/value structure with history) witch contains some sort of value that can be strings, numbers or dates. The structure is something like this :
table Values {
Id int,
Date datetime, -- for history
Key nvarchar(50) not null,
Value nvarchar(50),
DateValue datetime,
NumberValue numeric(19,9)
}
I want to put the raw value in the Value column and try to put the same value
in the DateValue column when i'm able to cast it to Datetime
in the NumberValue column when i'm able to cast it to a number
Those two typed columns would make all sort of aggregation and manipulation much easier and faster later.
That's it, now you know why i'm asking this strange question.
============
Thanks in advance for your help.
You could also try a Derived Column component and test the value of the potential date/number field or simply cast it and redirect any errors as being the NULL values for these two fields.
(1) If you just simply cast the field every time with a statement like this in the Derived Column component: (DT_DATE)[MYPOTENTIALDATE] - you can redirect the rows that fail this cast and manipulate the data from there.
OR
(2) You can do something like this in the Derived Column component: ISNULL([MYPOTENTIALDATE]) ? '2099-01-01' : (DT_DATE)[MYPOTENTIALDATE]. I generally send through '2099-01-01' when a date is NULL rather than messing with NULL (works better with Cubes, etc).
Of course (2) won't work if the [MYPOTENTIALDATE] field comes through as other things other than a DATETIME or NULL, i.e., sometimes it is a word like "hello".
Those are the options I would explore, good luck!
In dealing with this same sort of thing I found the error handling in SSIS was not specific enough. My approach has been to actually create an errors table, and query a source table where the data is stored as varchar, and log errors to the error table with something like the below. I have one of the below statements for each column, because it was important for me to know which column failed. Then after I log all errors, I do a INSERT where I select those records in SomeInfo that do not have an errors. In your case you could do more advanced things based on the ColumnName in the errors table to insert default values.
INSERT INTO SomeInfoErrors
([SomeInfoId]
,[ColumnName]
,[Message]
,FailedValue)
SELECT
SomeInfoId,
'PeriodStartDate',
'PeriodStartDate must be in the format MM/DD/YYYY',
PeriodStartDate
FROM
SomeInfo
WHERE
ISDATE(PeriodStartDate) = 0 AND [PeriodStartDate] IS NOT NULL;
Tru using a conditional split and have the records where the data is a date go along one path and the other go along a different path where they are updated to nullbefore being inserted.