SQL Syntax: SQL Server vs. Teradata - sql-server

I've been querying against Teradata servers with SQL Assistant for years, but now have to work with a SQL Server. I've been stumbling over my code for hours, having a hard time figuring out which pieces of syntax need to be updated.
Does anyone know of a good resource for converting logic?
Here's an example -- I was loading .txt data into a temp table:
In Teradata, the following works:
CREATE MULTISET TABLE USER_WORK.TABLE1 (
VAR1 CHAR(3)
,VAR2 CHAR(5)
,VAR3 DECIMAL(12,2) )
PRIMARY INDEX (VAR1, VAR2);
In SQL Server, I was able to get the following to work:
CREATE TABLE #TABLE1 (
VAR1 VARCHAR(20)
,VAR2 VARCHAR(20)
,VAR3 VAR(20) );
(Main differences: No "Multiset"; all variables read in as VARCHAR & and I couldn't get any length shorter than 20 to work; I couldn't figure out how to define a functional index)
Mostly wondering if there is some sort of pattern behind migrating the logic - it's painful to have to look up every single piece of failed code, and to sort out of it will actually run on SQL Server.

A few points...
The # prefix in your SQL Server attempt defines a local temporary table. It's visible to your session only, and it will go away when the session ends. I think it's similar to a VOLATILE table in Teradata. Is that what you wanted?
SQL Server tables are MULTISET by default so SQL has no equivalent keyword.
If you were having trouble with CHAR column sizes it was most likely a syntax error elsewhere. CHAR columns can be from 1 to 8,000 characters long, using a single-byte character set.
SQL Server doesn't have a PRIMARY INDEX. As I understand it, the equivalent in SQL Server is a CLUSTERED index.
So your exact table structure in SQL Server would be like this:
CREATE TABLE USER_WORK.TABLE1 (
VAR1 CHAR(3)
,VAR2 CHAR(5)
,VAR3 DECIMAL(12,2));
And for the index (the name can be whatever you want):
CREATE CLUSTERED INDEX TABLE1_FOO ON USER_WORK.TABLE1(VAR1, VAR2);

You can create the exact same schema in sql server as well but the syntax will be a bit different.
I would translate your teradata table as below:
CREATE TABLE TABLE1
( VAR1 CHAR(3) NOT NULL
,VAR2 CHAR(5) NOT NULL
,VAR3 DECIMAL(12,2)
,PRIMARY KEY (VAR1, VAR2)
);
GO
You can still have CHAR(3) and CHAR(5) data types for VAR1 and VAR2 columns, but you have to make them non-nullable column since they are going to be Primary key columns ( requirement in sql server).
Sql server also has data type decimal(12,2) you can use it for your VAR3 column. finally the composite primary key can be part of the table definition as shows above. tar

Some Teradata - SQL Server Management Studio (SSMS) Differences:
• Extract(MONTH from Column) = DATEPART(MONTH, Column)
• To comment a block of code, highlight it then click ‘Ctrl /’ (‘Ctrl Alt /’ to remove)
• DATE() (& TIME()) = GETDATE()
• Datatype BYTEINT = TINYINT
• Datatype LONG VARCHAR = VARCHAR(Max) (64,000 characters)
• ADD_MONTHS(Column, 2) = DATEADD(MONTH, 2, Column)
• String1 || ’ ‘ || String2 = String1 + ‘ ‘ + String2
• SELECT * FROM TABLE SAMPLE 50 = SELECT TOP 50 * FROM TABLE
• GROUP BY ROLLUP(1) = GROUP BY ‘Column’ WITH ROLLUP
• SUBSTRING ('SQL Tutorial' FROM 4 FOR 2) = SUBSTRING('SQL Tutorial', 4, 2)
• TRIM (TRAILING FROM <expression>) = RTRIM(<expression>)
• TRIM (LEADING FROM <expression>) = LTRIM(<expression>)
• NVL(Column,’’) = ISNULL(Column,’’)
I'm still trying to figure out the differences in writing update statements!

Related

Mssql encoding problem with special characters

We are using the node-mssql package to insert into and read out of our azure mssql database.
The database is very simple, because it is just used as a key/value cache, where the value can be quite long and also contain special characters.
DB Schema:
create table cache
(
id int identity
constraint cache_pk
primary key nonclustered,
cacheKey varchar(500),
ttl bigint,
value varchar(max)
)
go
create index cache_cacheKey_index
on cache (cacheKey desc)
go
create index cache_ttl_index
on cache (ttl)
go
For some reason, when I insert values into "value", some special characters are not treated well.
Dash – example
turns into:
Dash  example
I have seen the same thing happening with the french apostrophe.
I also tried to change the collation already, but that did not help.
Also tried it by using nvarchar(max) as column type.
This is the insert code (including the sql):
const result = await conn.request()
.input('key', mssql.VarChar, key)
.input('value', mssql.Text, value)
.input('ttl', mssql.BigInt, cacheEndTime)
.query`INSERT INTO cache (cacheKey, value, ttl) VALUES (#key, #value, #ttl)`;
Can you please help with a correct table structure or sql statement to make this work?
I'm not sure if can help you, but have you checked the collation of the table, the database, and the server? The collate have differents levels.
The answer for your question are in one of this items:
Server collation
Table collation
Field collation
Cast the insert text
For example, if you create nvarchar (I recommend if you have international scenario) field, cast the text insert like N'text to insert'.
It will work ;)
I have found the answer.
Like #RealSeik and #Larnu already stated it was probably not a problem with the database or the queries themselves, but rather an input problem.
I realized, that node-sass has a type for Unicode text, where they took care of casting it correctly.
So instead of mssql.Text I changed it to mssql.NText.
So now the insert command looks as follows:
const result = await conn.request()
.input('key', mssql.VarChar, key)
.input('value', mssql.NText, value)
.input('ttl', mssql.BigInt, cacheEndTime)
.query`INSERT INTO cache (cacheKey, value, ttl) VALUES (#key, #value, #ttl)`;
I have also added collations to my other scripts, for good measure as well.
(that alone did not help, but for good measure)
ALTER DATABASE MyDbName
COLLATE Latin1_General_100_CI_AI_SC_UTF8 ;
create table cache
(
id int identity
constraint cache_pk
primary key nonclustered,
cacheKey varchar(500) COLLATE Latin1_General_100_CI_AI_SC_UTF8,
ttl bigint,
value varchar(max) COLLATE Latin1_General_100_CI_AI_SC_UTF8
)
go
create index cache_cacheKey_index
on cache (cacheKey desc)
go
create index cache_ttl_index
on cache (ttl)
go

SQL Server : identity and autoincrement for varchar

This is my first question on this platform. I am working on a database project. I want to use autoincrement for my primary key for id, but also want to add an alphabet before it. Are there other ways to do it apart from using 2 columns declaring one as identity and casting the other? I have worked with stored procedures and triggers.
Thank you
PS: I want to do it using one column if possible
You won't be able to do this with just one column.
The best solution is to use
an ID INT IDENTITY(1,1) column to get SQL Server to handle the automatic increment of your numeric value
a computed, persisted column to convert that numeric value to the value you need
So try this:
CREATE TABLE dbo.tblCompany
(
ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
CompanyID AS 'CMP-' + RIGHT('00000' + CAST(ID AS VARCHAR(5)), 5) PERSISTED,
.... your other columns here....
)
Now, every time you insert a row into tblCompany without specifying values for ID or CompanyID:
INSERT INTO dbo.tblCompany(Col1, Col2, ..., ColN)
VALUES (Val1, Val2, ....., ValN)
then SQL Server will increase your ID value, and CompanyID will contain values like CMP-00001, CMP-00002,...... and so on - automatically. The CompanyID column will be fill automatically, by SQL Server, upon inserting a new row - so there's no need for triggers or stored procedures or anything else - just this declaration in your table definition.
UPDATE: if you're using SQL Server 2012 or newer, you can do it with just one column - if you also create a SEQUENCE - like this:
CREATE SEQUENCE SEQ_CompanyID
AS INT
START WITH 1000
INCREMENT BY 1;
CREATE TABLE dbo.Company
(
CompanyID VARCHAR(20) NOT NULL
CONSTRAINT DF_CompanyID
DEFAULT('CMP-' + CAST(NEXT VALUE FOR dbo.SEQ_CompanyID AS VARCHAR(10))),
CompanyName VARCHAR(100) NOT NULL,
----- other columns here
)
Now if you make sure to insert with omitting the CompanyID column in the insert statement, like this:
INSERT INTO dbo.Company (CompanyName)
VALUES ('Company #1'), ('Company ABC'), ('Company Three');
then you get CMP-1001', 'CMP-1002 etc. as your CompanyID, again, automatically handled by SQL Server upon inserting a new row.

At a Format Constraint to A Create Table Statement

I am creating a table in SQL Server for one of my customers that is needing an Access DB converted to SQL Server. ON the tables Access has masked a column a certain way. They have a number lets say TP001111 and when I pull the value into SQL Server I get 1111. I have a table called VendorNumber and I need to format this number.
CREATE TABLE VendorNumber
(
V_ID NVARCHAR(8) NOT NULL PRIMARY KEY,
V_Name NVARCHAR(30) NOT NULL
)
I have tried researching how to do this and I can't find a good example. What is the best way to have this value formatted when it is inserted into the table. I need to have it inserted as TP001111. The current code I have to format the column is:
UPDATE VendorNumber
SET V_ID = 'TP' + RIGHT((REPLICATE('0',6) + TPPRM_ID),6)

Microsoft SQL Server 2014 sequence

A brief description, I am building a VB.NET program from scratch including database. Therefore I am required to set the unique transaction ID for each table for example header_id, detail_id, order_number, and lots more that require any running increment number. I am upgrading from SQL Server 2005 to SQL Server 2014 so that I can have a built-in SEQUENCE for the running number job.
My current situation (SQL Server 2005, VB.NET) is I am using a table to store all the running number and a stored procedure to execute the running numbers from my VB.NET program. For example in Sales Order, I will pass a hard-coded parameter to the stored procedure to find the value in the table and then increase the number by 1 and then insert it into the Sales Order table.
Before I start migrating the database and redesign the table structure, I would like to know if I am on the correct start, which means for each table I have to assign a specific sequence for it? Please guide.
Usually you do not need a SEQUENCE to generate unique, increasing identity values for single tables. Even with SQL Server 2005, you have two simpler options for that:
Define an IDENTITY column. For example:
CREATE TABLE Orders
(
OrderId INT IDENTITY(1,1) NOT NULL,
… -- ^^^^^^^^^^^^^
); -- very much like an unnamed sequence that START WITH 1 INCREMENT BY 1
When INSERT-ing into this table, you do not need to specify a value for OrderId, it will be chosen for you by the RDBMS. The resulting IDs will be unique (but there is the possibility of gaps).
Instead of using integer number IDs, use GUIDs:
CREATE TABLE Orders
(
OrderId UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL DEFAULT (NEWSEQUENTIALID()),
…
);
The DEFAULT constraint means you don't have to explicitly choose a value for OrderId when INSERT-ing; the RDBMS will generate a value for you.
P.S.: NEWSEQUENTIALID() ensures that the generated GUIDs are steadily increasing. This is important if the GUID column is used for clustering (i.e. when you have a PRIMARY KEY CLUSTERED (OrderId ASC) constraint), as mentioned in a comment below. If the column is not used for clustering and it's only important that GUIDs are unique, but not necessarily increasing, then you can also use NEWID() instead.
Of course you can also use a SEQUENCE, but such a one has no added benefit over the above two (simpler) solutions. This changes when you have to create unique IDs across several tables, for example:
CREATE SEQUENCE OrderIds START WITH 1 INCREMENT BY 1;
CREATE TABLE FlowerOrders
(
OrderId INT NOT NULL DEFAULT (NEXT VALUE FOR OrderIds),
…
);
CREATE TABLE FlowerPotOrders
(
OrderId INT NOT NULL DEFAULT (NEXT VALUE FOR OrderIds)
…
);
This way it should be impossible that FlowerOrders and FlowerPotOrders contain overlapping OrderIds.

Correct SQL to convert mySQL tables to SQL Server tables

I have a number of tables I need to convert from mySQL to SQL Server.
An Example of a mySQL Table is
CREATE TABLE `required_items` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'Unique Barcode ID',
`fk_load_id` INT( 11 ) NOT NULL COMMENT 'Load ID',
`barcode` VARCHAR( 255 ) NOT NULL COMMENT 'Barcode Value',
`description` VARCHAR( 255 ) NULL DEFAULT NULL COMMENT 'Barcode Description',
`created` TIMESTAMP NULL DEFAULT NULL COMMENT 'Creation Timestamp',
`modified` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Modified Timestamp',
FOREIGN KEY (`fk_load_id`) REFERENCES `loads`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE = InnoDB CHARACTER SET ascii COLLATE ascii_general_ci COMMENT = 'Contains Required Items for the Load';
And a trigger to update the created date
CREATE TRIGGER required_items_before_insert_created_date BEFORE INSERT ON `required_items`
FOR EACH ROW
BEGIN
SET NEW.created = CURRENT_TIMESTAMP;
END
Now I need to create tables similar to this in SQL Server. There seems to be a lot of different data types available so I am unsure which to use.
What data type should I use to the primary key column
(uniqueidentifier, bigint, int)?
What should I use for the timestamps
(timestamp, datatime, datetime2(7))?
How should I enforce the created
and modified timestamps (currently I am using triggers)?
How can I enforce foreign key constraints.
Should I be using Varchar(255) in SQL Server? (Maybe Text, Varchar(MAX) is better)
I am using Visual Studio 2010 to create the tables.
First of all, you can probably use PHPMyAdmin (or something similar) to script out the table creation process to SQL Server. You can take a look at what is automatically created for you to get an idea of what you should be using. After that, you should take a look at SSMS (SQL Server Management Studio) over Visual Studio 2010. Tweaking the tables that your script will create will be easier in SSMS - in fact, most database development tasks will be easier in SSMS.
What data type should I use to the primary key column (uniqueidentifier, bigint, int)?
Depending on how many records you plan to have in your table, use int, or bigint. There are problems with uniqueidentfiers that you will probably want to avoid. INT vs Unique-Identifier for ID field in database
What should I use for the timestamps (timestamp, datatime, datetime2(7))?
timestamps are different in SQL Server than in MySQL. Despite the name, a timestamp is an incrementing number that is used as a mechanism to version rows. http://msdn.microsoft.com/en-us/library/ms182776%28v=sql.90%29.aspx . In short though, datetime is probably your best bet for compatibility purposes.
How should I enforce the created and modified timestamps (currently I am using triggers)?
See above. Also, the SQL Server version of a "Timestamp" is automatically updated by the DBMS. If you need a timestamp similar to your MySQL version, you can use a trigger to do that (but that is generally frowned upon...kind of dogmatic really).
How can I enforce foreign key constraints.
You should treat them as you would using innoDB. See this article for examples of creating foreign key constraints http://blog.sqlauthority.com/2008/09/08/sql-server-%E2%80%93-2008-creating-primary-key-foreign-key-and-default-constraint/
Should I be using Varchar(255) in SQL Server? (Maybe Text, Varchar(MAX) is better)
That depends on the data you plan to store in the field. Varchar max is equivalent to varchar(8000) and if you don't need varchar(255), you can always set it to a lower value like varchar(50). Using a field size that is too large has performance implications. One thing to note is that if you plan to support unicode (multilingual) data in your field, use nvarchar or nchar.

Resources