INSERT INTO causing nulls in columns - sql

I'm trying to concatenate two columns and add a comma and space between them in SQL Server 2014.
Here's the code I'm using (redacting the table name for privacy reasons)
INSERT INTO Table (EntityName)
SELECT CONCAT(MailingLine1, ', ', MailingState)
FROM Table
This is concatenating the strings correctly, but in the process, it's causing all other columns and all other rows to read as NULL and wipes the data from the table.
There are roughly 30 columns that already have data within them
Any thoughts?

If you are looking to add a new column with this function CONCAT(MailingLine1, ', ', MailingState) so you can use a computed column
--if [EnityName] already exists in the table you have to drop it first
alter table TABLE
drop column [EntityName]
alter table TABLE
add [EntityName] as CONCAT(MailingLine1, ', ', MailingState)
If you don't want to add a computed column you can follow #GordonLinoff answer (use UPDATE command)
Else, If you are looking to insert new rows not to update rows, the issue is that you are only inserting values in EntityName column and ignoring all other columns, you can assign values as the following (assuming you have 3 columns)
Insert into Table (EntityName,EntityName2,EntityName3)
SELECT CONCAT(MailingLine1, ', ', MailingState),Value1,Value2 FROM Table
Where Value1,Value2 can be columns from the table, or fixed value i.e. 'John'

Set a default value for the other volums, a not NULL value. (See example)
ALTER TABLE {table_name} ADD DEFAULT {dafault_value} FOR {column_name}

I'm guessing you want update, not insert:
update Table
set EntityName = CONCAT(MailingLine1, ', ', MailingState);

Related

SQL insert from select, but set some values by hand

Let's say that I have table with A LOT of columns. I have one column with primary key that has autoincrement set to 1. I want to insert a new row and in this new row I have following requirements:
The row must have generated ID
All non-specified columns have to be copied from row with id='9999'
I have to be able to set some values of columns by hand (for example columns name and age
I have tried:
Insert Into demo_table
Select * From demo_table Where id='9999';
However, I get this error:
An explicit value for the identity column in table 'demo_table' can only be specified when a column list is used and IDENTITY_INSERT is ON.
What do I need:
I want to duplicate a row -> let the id be set by database (I have PK and autoincrement configured) -> set some columns by hand -> have other column's values duplicated, without specifying column names (as I have a lot of columns and their names could change in future.)
Form of solution:
I would prefer if I was able to achive this using only one query. If necessary, I have stored procedures available.
My question:
Is this even possible? How could I achive such query/procedure?
There is a way to build sql query by table schema:
USE <databaseName>
DECLARE
#SourceTableName NVARCHAR(255) = <TableName>,
#SqlQuery NVARCHAR(MAX)
IF OBJECT_ID('tempdb.dbo.#IdentityCols', 'U') IS NOT NULL
DROP TABLE #IdentityCols;
CREATE TABLE #IdentityCols(
ColumnName NVARCHAR(255)
)
INSERT INTO #IdentityCols
SELECT
--TABLE_NAME,
COLUMN_NAME
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1 AND TABLE_NAME = #SourceTableName
UNION
SELECT
--o.name,
c.name
FROM
sys.objects o inner join
sys.columns c on o.object_id = c.object_id
WHERE
c.is_identity = 1 AND o.name = #SourceTableName
--STRING_AGG in SQL SERVER 2017 and greater. As aproach for early versions is cursor or loop
SELECT #SqlQuery = 'SELECT ' + STRING_AGG(COLUMN_NAME, ',') + ' FROM ' + #SourceTableName
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME=#SourceTableName AND COLUMN_NAME NOT IN (Select ColumnName FROM #IdentityCols)
exec sp_executesql #SqlQuery
For more information you can see this questions:
How can I show the table structure in SQL Server query?
How do you determine what SQL Tables have an identity column programmatically
How to concatenate text from multiple rows into a single text string in SQL Server
SQL Server Loop through Table Rows without Cursor
SQL Server loop - how do I loop through a set of records
For anyone interested, how I've solved this problem:
After I've read your comments (thanks btw) and some threads online, I've realized why I cannot do what I asked. However, I've come seen solution to similar problem somewhere, where they wanted to select * except one specific column, they solved it like this:
copied the entire table
selected from there.
I've come up with similar solution to my problem
-- check data, remove after testing
select * from demo_table order by ID desc;
-- create table with one column I want to duplicate
select * into Temp_demo_table from demo_table where ID=9999;
-- drop id, so it does not get included in the inter-table insert
alter table Temp_demo_table
drop column ID;
-- update columns that I need to modify, doesn't have to have WHERE clause, becuase there's only one row there
update Temp_demo_table set MyCustomProperty='abc', name=NULL, age=NULL
-- insert the desired and edited row
insert into demo_table
select * from Temp_demo_table;
-- drop the temp table
drop table Temp_demo_table;
-- check data, remove after testing
select * from demo_table order by ID desc;
I realize how inefficient this is, however the function (on my api) executing this command will not be called so often (max 100 times per day). I believe that this query could be optimized, however I do not have sufficient knowledge to do it at this moment (100% going to put it in my TODO :D).
Edit-1:
Just found out that you can write queries in oracle db like this:
(select * from demo_table) - (select name, age from demo_table)
I currentlly don't know if I can apply this to sql server, however as soon as I have an access to mssql, I'll try it out and keep this answear updated!

How to replace all the NULL values in postgresql?

I found the similar question and solution for the SQL server. I want to replace all my null values with zero or empty strings. I can not use the update statement because my table has 255 columns and using the update for all columns will consume lots of time.
Can anyone suggest to me, how to update all the null values from all columns at once in PostgreSQL?
If you want to replace the data on the fly while selecting the rows you need:
SELECT COALESCE(maybe_null_column, 0)
If you want the change to be saved on the table you need to use an UPDATE. If you have a lot of rows you can use a tool like pg-batch
You can also create a new table and then swap the old one and the new one:
# Create new table with updated values
CREATE TABLE new_table AS
SELECT COALESCE(maybe_null_column, 0), COALESCE(maybe_null_column2, '')
FROM my_table;
# Swap table
ALTER TABLE my_table RENAME TO obsolete_table;
ALTER TABLE new_table RENAME TO my_table;

SQL only delete values in specific colums?

What I am trying to do is delete all rows from a table, but leave values in 1 specific column from the table.
For example the table 'member' with the columns 'membernumber', 'name', lastname' and 'zipcode', I only want to keep all the zipcodes as they are, but delete all other data.
If you want to change your table structure, you use Alter Table along with Drop Column instead of Delete which is for your records. Here is a sample:
ALTER TABLE member
DROP COLUMN membernumber, name, lastname

Query results to temp, then move to mast table

I don't know what I am doing. Extra new at this. Below I am trying to make corrections to the data on a column, with out losing any of the data, just overriding it. In this Column, some of the cells have characters spaces (spacebar) in them so it dose not show up as "NULL".
In my fist attempt, I can see the query data and it looks good, 100% correct. But don't know how to put that data into the table I got it from. So I need to replace the data in column 'Speedlink_IP' with my Queried results.
Thanks every one in advance!
1st Attempt -
SELECT NULLIF(LTRIM(RTRIM(Speedlink_IP)), '')
As Speedlink_IP
FROM Master_IP_Data
INSERT INTO TEMP1 (col1)
2nd attempt -
CREATE TABLE TEMP1 (
col1 varchar (50) NULL
);
SELECT NULLIF(LTRIM(RTRIM(Speedlink_IP)), '')
As Speedlink_IP
FROM Master_IP_Data
INSERT INTO TEMP1 (col1)
INSERT INTO dbo.Master_IP_Data (Speedlink_IP)
SELECT col1
FROM TEMP1
;
DROP Table TEMP1
You seem to be looking for a simple UPDATE statement.
UPDATE Master_IP_Data
SET Speedlink_IP = NULL
WHERE LTRIM(RTRIM(Speedlink_IP)) = ''
This query will turn to NULL values of Speedlink_IP that contains only spaces. You don't need to use a temporary table for this.

SQL Index on changed column

Is it possible to create an Index on column with changes of this column.
For example - I have a column A (nvarchar), But in query I should to replace values from this column to compare with values in list. Classical index will work only if I use original values from column A.
The query looks like next
SELECT
*
FROM
MyTable
WHERE
REPLACE(A, ' ', '') IN ('aasa', 'asa', 'wew','wewe')
You can create a computed column and then create an index on it.
Note: SQL Server Index key columns have a 900 byte size limit. Since your column is NVARCHAR, it consumes 2 bytes for each character. So, let's can cap the index at 400 characters (800 bytes).
To conserve space, we can further restrict this column to contain a value, only if it meets your required conditions.
ALTER TABLE MyTable
ADD A_NoSpace AS (CASE WHEN REPLACE(A, ' ', '') IN ('aasa', 'asa', 'wew','wewe') THEN LEFT(REPLACE(A, ' ', ''), 400) END) PERSISTED
CREATE NONCLUSTERED INDEX IX_A_NoSpace ON MyTable (A_NoSpace)
Being a PERSISTED column, calculation will take place only during INSERT or UPDATE operations.
You can now use this column in your query:
SELECT *
FROM
MyTable
-- Don't need to check if value is in the list,
-- because we're already doing this in the computed column definition
WHERE A_NoSpace IS NOT NULL