How to merge two columns in sql server - sql

I want to merge two columns from deferent tables and when run my query shows this error:
Cannot resolve collation conflict for column 1 in SELECT statement
Here is my query
select (problems.name + department.dep_name) as m, usere.Use_name
, emp_problems.op_date
from usere, department, problems, emp_problems
where usere.id = emp_problems.users_id and emp_problems.prob_id = problems.id
and emp_problems.dup_dep_id = department.id
and emp_problems.emp_id = 37 and emp_problems.months = 11 and emp_problems.years =2020

You need to ALTER one of the columns to change the collation, or use COLLATE clause as
CREATE TABLE dbo.MyTable
(
MyCol1 VARCHAR(20) COLLATE Latin1_General_100_CI_AI_SC,
MyCol2 VARCHAR(20) COLLATE Latin1_General_100_CI_AI
);
Using ALTER:
ALTER TABLE dbo.MyTable
ALTER COLUMN MyCol2 VARCHAR(50) COLLATE Latin1_General_100_CI_AI_SC;
Using COLLATE clause:
INSERT INTO dbo.MyTable VALUES
('Foo', 'Bar');
/* This will throw the error */
SELECT CONCAT(MyCol1, MyCol2) FROM dbo.MyTable;
/* This won't */
SELECT CONCAT(MyCol1, MyCol2 COLLATE Latin1_General_100_CI_AI_SC) FROM dbo.MyTable;
Take a look at Set or Change the Column Collation
Here is a db<>fiddle

Related

Insert Into HANA Table Specifying Columns

I'm coming from a Teradata environment where
create table mytable
(
first_column varchar(50),
second_column varchar(50),
third_column varchar(50)
)
insert into mytable values (first_column = 'one', second_column = 'first')
insert into mytable values (first_column = 'two', third_column = 'second')
is possible. This does not seem to be possible in HANA even with default specified
create column table mytable
(
"FIRST_COLUMN" varchar(50) default null,
"SECOND_COLUMN" varchar(50) default null,
"THIRD_COLUMN" varchar(50) default null
)
I could create a row with a unique ID specifying NULLs for all the fields and then UPDATE the columns I want using the ID which seems time consuming and awkward or is there a better way?
Use the standard syntax:
insert into mytable (first_column, second_column)
values ('one', 'first');
This should work both in Hana and Teradata -- and any other database.

Using the identity column to add a value to a computed column

At times I need to store a temporary value to a field. I have a stored procedure that adds it using:
Insert new record first then
SELECT #Record_Value = SCOPE_IDENTITY();
UPDATE ADMIN_Publication_JSON
SET NonPubID = CAST(#Record_Value as nvarchar(20)) + '_tmp'
WHERE RecID = #Record_Value
It simply takes the identity value and adds an '_tmp' to the end. Is there a way that I can create a default value in the table that would do that automatically if I did not insert a value into that field?
The NonPubID column is just a NVARCHAR(50).
Thanks
You could write a trigger, that replaces NULL with that string upon INSERT.
CREATE TRIGGER admin_publication_json_bi
ON admin_publication_json
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE apj
SET apj.nonpubid = concat(convert(varchar(20), i.id), '_tmp')
FROM admin_publication_json apj
INNER JOIN inserted i
ON i.id = apj.id
WHERE i.nonpubid IS NULL;
END;
db<>fiddle
Downside: You cannot explicitly insert NULLs for that column, should that be desired.
Check out NewKey col below:
CREATE TABLE #Table
(
ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
IDValue VARCHAR(1) ,
ModifiedDT DATETIME NULL,
NewKey AS ( CONVERT(VARCHAR(100),ID)+'_Tmp' )
)
INSERT #Table( IDValue, ModifiedDT )
SELECT 'A', GETDATE()
UNION ALL
SELECT 'Y', GETDATE() - 1
UNION ALL
SELECT 'N', GETDATE() - 5
SELECT * FROM #Table

Inserting a Row of Default Values into a Temporary Table

I'm attempting to select a row of default values from a table. However, I don't want to create a new row in my original table. My original table has non-null default values (all blanks or zeros) defined for all columns (except for the one unique identifier). I begin by creating the temporary table:
SELECT
TOP 0 *
INTO
#Table
FROM
Database.dbo.Table
Then I examine the empty table:
SELECT
*
FROM
#Table
Everything looks fine so far. There are no rows, but I can see all the columns from my original table. Then, I attempt to insert a single row into the table with default values for all the columns:
INSERT INTO
#Table
DEFAULT VALUES
Rather than success, I get the following error:
Cannot insert the value NULL into column 'Column',
table 'tempdb.dbo.#Table___0001A';
column does not allow nulls. INSERT fails.
I next tried to insert a row with just one field defined.
INSERT INTO
#Table
(Column)
VALUES
('Value')
Same results. It appears that the definitions of the column default values from my original table were not included in the creation of the temporary table. Any suggestions?
When you create a temp table via SELECT ... INTO #Table the temp table gets all columns from the main table, but no constraints or indexes.
Obviously, you can explicitly create temp table with all necessary constraints.
One more option is to actually insert a row into the main table, let the engine populate it with default values, then read inserted values and insert them into the temp table. All this in a transaction. Then rollback the transaction, so that the main table remains as it was.
To make it work you need to use table variable instead of temp table, though, because temp tables participate in transactions as normal tables, but table variables don't. It means that you have to define the table variable in advance, so you need to know what columns your original table has. But, at least, you don't have to know the definition of default constraints.
Also, if your main table has an INDENTITY column, this insert-rollback will create a gap in identity values.
Sample table
CREATE TABLE [dbo].[MainTable](
[Col1] [int] NOT NULL,
[Col2] [nvarchar](50) NOT NULL,
[Col3] [date] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[MainTable] ADD CONSTRAINT [DF_MainTable_Col1]
DEFAULT ((123)) FOR [Col1]
GO
ALTER TABLE [dbo].[MainTable] ADD CONSTRAINT [DF_MainTable_Col2]
DEFAULT ('qwerty') FOR [Col2]
GO
ALTER TABLE [dbo].[MainTable] ADD CONSTRAINT [DF_MainTable_Col3]
DEFAULT (getdate()) FOR [Col3]
GO
Query
DECLARE #T TABLE (Col1 int, Col2 nvarchar(50), Col3 date);
BEGIN TRANSACTION;
INSERT INTO dbo.MainTable
OUTPUT inserted.Col1, inserted.Col2, inserted.Col3
INTO #T (Col1, Col2, Col3)
DEFAULT VALUES;
ROLLBACK TRANSACTION;
SELECT *
FROM #T;
Result
+------+--------+------------+
| Col1 | Col2 | Col3 |
+------+--------+------------+
| 123 | qwerty | 2017-08-29 |
+------+--------+------------+
You need to create your temp table and include the default definitions in it.
--Check to see if table exists
--If it does, drop it
IF OBJECT_ID('tempdb.dbo.#Table', 'U') IS NOT NULL
DROP TABLE #Table
--Create temp table with default value
CREATE TABLE #Table
(
columnA INT DEFAULT (1),
columnB INT DEFAULT (2),
columnC INT DEFAULT (3)
)
--Insert a row of default values
INSERT INTO
#Table
DEFAULT VALUES
--See it
SELECT *
FROM #Table
--Drop temp table after you are done
DROP TABLE #Table
Build your row from the temptdb catalog?
SELECT c.name AS 'Colunmn'
, TYPE_NAME(c.user_type_id) AS 'Type'
, CASE c.is_nullable WHEN 0 THEN 'No Nulls'
ELSE '' END AS 'Nullable'
, CASE c.default_object_id WHEN 0 THEN ''
ELSE 'Y' END AS 'Has_Default'
, dft.definition as Default_Value
, CASE ISNULL(c.max_length, -1) WHEN -1 THEN 'Variable'
ELSE CAST(c.max_length AS VARCHAR) END AS 'Length'
, ISNULL('['+OBJECT_NAME(fkc.referenced_object_id)+'].['+Cref.name+']', ' ') AS ForeignKeyInto
FROM tempdb.sys.tables t
JOIN tempdb.sys.columns c ON t.object_id = c.object_id
LEFT JOIN tempdb.sys.foreign_key_columns FKC ON c.object_id = fkc.Parent_object_id
AND fkc.parent_column_id = c.column_id
LEFT JOIN tempdb.sys.columns cref ON fkc.referenced_column_id = cref.column_id
AND fkc.referenced_object_id = cref.object_id
left join tempdb.sys.default_constraints dft on c.default_object_id = dft.object_id
WHERE t.name like '#temp%'
ORDER BY t.name
, c.name;

Compare Column names from 2 diff table in diff db in MS SQL

I am trying to get column names from 2 diff tables in diff db and compare them to see if there is any extra column in any table. They should match exactly. One possible solution could be getting all the column names from both table and dump in a temp table side by side and compare? Pls help.
IF OBJECT_ID('tempdb..#myTable') IS NOT NULL DROP TABLE #myTable
CREATE table #myTable (
table1 varchar(100) null,
table2 varchar(100) null
)
INSERT INTO #myTable (table1)
SELECT name
FROM sys.columns
WHERE object_id = OBJECT_ID('table1')
select * from #mytable
DROP TABLE #mytable
I modified your query to this
IF OBJECT_ID('tempdb..#myTable') IS NOT NULL DROP TABLE #myTable
CREATE table #myTable
(
rowNum int IDENTITY(1,1),
table1 varchar(100) null
)
GO
IF OBJECT_ID('tempdb..#myTable2') IS NOT NULL DROP TABLE #myTable2
CREATE table #myTable2
(
rowNum int IDENTITY(1,1),
table2 varchar(100) null
)
GO
USE database1 --your 1st database name here
GO
INSERT INTO #myTable (table1)
(
SELECT
name
FROM sys.columns
WHERE object_id = OBJECT_ID('Table_1'))
GO
USE database2 -- your 2nd database name here
GO
INSERT INTO #myTable2 (table2)
(
SELECT
name
FROM sys.columns
WHERE object_id = OBJECT_ID('Table_2'))
GO
SELECT table1,table2
FROM #myTable m
FULL OUTER JOIN #myTable2 m2 ON m.rowNum = m2.rowNum
ORDER BY table1,table2
DROP TABLE #mytable
DROP TABLE #mytable2

PostgreSQL insert and ignore multiple columns

I have newly created table with 4 unique fields: nsn, slug, part_no, mfg_sku.
I'm trying to insert into this table approx. 2 million rows from multiple tables, which has also repeating rows.
so the main question is...
how to emulate insert ignore in this case?
Select distinct based on multiple columns or what do you suggest?
Here is the data that I want to insert to Part table
SELECT "PartOld".id,
"PartOld"."PartNo",
"PartOld"."Manufacturer",
"PartOld"."Slug",
"PartOld"."Description",
"PartOld"."NSN",
NULL::numeric AS price,
"PartOld".name,
NULL::character varying AS mfg_sku
FROM "PartOld"
UNION
SELECT part_item.id,
NULL::character varying AS "PartNo",
part_item.manufacturer AS "Manufacturer",
NULL::character varying AS "Slug",
part_item.details AS "Description",
part_item.msn AS "NSN",
NULL::numeric AS price,
part_item.name,
part_item.mfg_sku
FROM part_item_fetched part_item
And Here is the Part table.
DROP TABLE IF EXISTS "electronic_parts"."Part";
CREATE TABLE "electronic_parts"."Part" (
"id" int4 NOT NULL DEFAULT nextval('"Part_id_seq"'::regclass),
"part_no" varchar COLLATE "default",
"manufacturer" varchar COLLATE "default",
"description" text COLLATE "default",
"slug" varchar COLLATE "default",
"nsn" varchar COLLATE "default",
"price" numeric,
"name" varchar COLLATE "default",
"mfg_sku" varchar COLLATE "default"
)
WITH (OIDS=FALSE);
ALTER TABLE "electronic_parts"."Part" OWNER TO "root";
-- ----------------------------
-- Primary key structure for table Part
-- ----------------------------
ALTER TABLE "electronic_parts"."Part" ADD PRIMARY KEY ("id") NOT DEFERRABLE INITIALLY IMMEDIATE;
-- ----------------------------
-- Indexes structure for table Part
-- ----------------------------
CREATE UNIQUE INDEX "part_u1" ON "electronic_parts"."Part" USING btree(part_no COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST);
CREATE UNIQUE INDEX "part_u2" ON "electronic_parts"."Part" USING btree(nsn COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST);
CREATE UNIQUE INDEX "part_u3" ON "electronic_parts"."Part" USING btree(mfg_sku COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST);
Use
INSERT INTO ...
(SELECT ...)
ON CONFLICT DO NOTHING;
This has been available since 9.5, see the documentation.
You can filter your input with anti joins (tipically with NOT EXISTS() or LEFT JOIN + IS NULL):
WITH data AS (
-- your query here
SELECT ...
UNION ALL ...
),
conflicting_ids AS (
SELECT id FROM data GROUP BY id HAVING COUNT(*) > 1
),
conflicting_part_nos AS (
SELECT part_no FROM data GROUP BY part_no HAVING COUNT(*) > 1
),
conflicting_nsns AS (
SELECT nsn FROM data GROUP BY nsn HAVING COUNT(*) > 1
),
conflicting_mfg_skus AS (
SELECT mfg_sku FROM data GROUP BY mfg_sku HAVING COUNT(*) > 1
)
INSERT INTO table_name (column_names)
SELECT d.*
FROM data d
WHERE NOT EXISTS(SELECT 1 FROM conflicting_ids a WHERE a.id = d.id)
AND NOT EXISTS(SELECT 1 FROM conflicting_part_nos a WHERE a.part_no = d.part_no)
AND NOT EXISTS(SELECT 1 FROM conflicting_nsns a WHERE a.nsn = d.nsn)
AND NOT EXISTS(SELECT 1 FROM conflicting_mfg_skus a WHERE a.mfg_sku = d.mfg_sku)
ON CONFLICT DO NOTHING
Notes: id is unique too, because it is the primary key. Also, because the conflicting rows are checked separately, you won't need UNION. You can use UNION ALL, which will be a slightly more efficient.