I wanted to add a column in MS SQL Server. Will it affect any existing stored procedures or triggers or dbms jobs etc? AFAIK, in Oracle once you add a new column to an existing table, you need to recompile any invalid objects. How bout in MS SQL Server?
Adding a column to an existing table, in theory and best practices world is easy, but in reality it is not always as easy as ALTER TABLE ADD COLUMN.
The risk is that any procedure, view or application code that uses a “Select *” or an “Insert Values <…>” (without column names explicitly stated) may not function, or may not function correctly, with an additional column added to the table.
Also note there could be temp tables, table variables and table value parameters built off the table that an additional column affects as well. Best practices and my database development guidelines says not to use the “Select *” or the “Insert Values <…>”.
For example, if you have a table with ID, Name, and Status columns in your table
DECLARE #Table TABLE (id INT, name VARCHAR(20), Status INT)
INSERT INTO #Table VALUES (1,'Name')
It will throw error Column name or number of supplied values does not match table definition. Because in this query, inserting only first two column values and Status is missing. If you add Status column value will not throw any error.
So you need to always mention column names in your INSERT query wherever used
DECLARE #Table TABLE (id INT, name VARCHAR(20), Status INT)
INSERT INTO #Table (id, name) VALUES (1,'Name')
If you didn't specify the column names in INSERT query and add new column to the table will affect that query. Please make sure whether you specified the column names.
Related
I have two tables in SQL Server:
Person
ID (PK, int, IDENTITY)
Name (varchar(100))
UploadedBy (varchar(50))
DateAdded (datetime)
PersonFile
ID (PK, int, IDENTITY)
PersonId (FK, int)
PersonFile (varchar(max))
I am reading in a large file (150MB), and I have a script component that can successfully parse the file into several columns. The issue is that I need to insert the first 3 columns of my parsed data row into my Person table first, then use the ID of that Row to insert the final column into my PersonFile table. Is there an easy way to do this in SSIS?
I suppose I could technically script everything out to handle inserts in the database, but I feel like in that case, I might as well just skip SSIS altogether and user powershell. I also thought about writing a procedure in SQL server and then passing the information to the procedure to handle inserts. But again, this seems very inefficient.
What's the best way for me to insert a row of data into two tables, if one of them has a foreign key constraint?
I think the best way is to use a stage table in the database to hold the parsed source file and then use stored procedures or SQL-query to load your tables. There is a lookup component in SSIS that can be used for your case but I try avoiding it for various reasons.
Create a table resembeling the source file, something like:
CREATE TABLE dbo.[SourceFileName](
Name nvarchar(100) NULL,
UploadedBy nvarchar(50) NULL,
DateAdded datetime NULL,
PersonFile nvarchar(max) NULL
)
Truncate the stage table. Use a dataflow component to get the source data. Use script or stored procedures to insert the source data in your destination table (begin with Person and the load PersonFile). Your SSIS dataflow should look something like this:
For the insert script for person do something like:
INSERT INTO dbo.Person (Name, UploadedBy,DateAdded)
SELECT Name,UploadedBy,DateAdded
FROM dbo.SourceFileName;
For the insert for PersonFile make a join to the destination table:
INSERT INTO dbo.PersonFile(PersonId,PersonFile)
SELECT
Person.ID,
SourceFile.PersonFile
FROM dbo.SourceFileName SourceFile
JOIN dbo.Person Person
ON Person.Name = SourceFile.Name
You should also add a UNIQUE CONSTRAINT to the column that identifies the person (Name for example).
One very common thing to do would be to stage the data first.
So you insert all columns into a table on the server, which also has an extra nullable column for the PersonID.
Then you’d have a stored procedure which inserts unique Person records into the Person table, and updates the staging table with the resulting PersonID, which is the extra field you need for the PersonFile insert, which could then be performed either in the same procedure or another one. (You’d call these procedures in SSIS with an Execute SQL Task.)
I suppose this could possibly be done purely in SSIS, for example with a Script Destination that performs an insert and retrieves the PersonID for a second insert, but I’m fairly sure performance would take a huge hit with an approach like that.
A simple question in Snowflake. I created a table with an identity column.
create table etl_test
(id int identity,
name string);
And tried to insert data into it. In my SQL Server world, I just need to provide the value for the name field.
insert into etl_test values('test');
I tried the same in Snowflake but I am getting an error
SQL compilation error: Insert value list does not match column list expecting 2 but got 1
How can I make sure that the value 'test' is inserted with id = 1?
You need to include the column name(s) you are using if you aren't inserting into all the columns:
insert into etl_test (name) values('test');
"Blind inserts" are antipattern regardless of RDBMS.
In your scenario, you need to specify column list and either remove id from column list or provide a DEFAULT for it.
INSERT INTO etl_test(id, name) VALUES (DEFAULT, 'test');
I have set some script that inserts data from an XML file into a SQL database. I am getting the following error.
Cannot insert the value NULL into column 'fighterID', table 'MMA Database.dbo.FIGHTERStemp'; column does not allow nulls. INSERT fails.
I have fighterID set as the primary key and will not allow NULLS. My intention is to have it number each row as they are inserted. I found one answer that advises to modify the column properties to be the identifier. However it will not let me adjust the columns properties without dropping and adding the table again.
I can do that - but what is the SQL syntax to set the identity specification settings? Am I going about this the right way?
It's pretty simple, just set the field with datatype INT (integer) and follow it with keyword IDENTITY. You can include the seed and increment values; e.g. start at 1, increment by 1, or just use the keyword IDENTITY for a 1,1 default.
CREATE TABLE MMA (FighterID INT IDENTITY (1,1), FighterInfo VARCHAR(MAX))
While inserting data into Primary key you can check the previous max id value and then increment it to next value before you insert a new row.
In SQL, you need to drop table before altering its specification. You can do this by taking backup into temp table then drop your main table and then re insert data from temp table.
I need to design a table in SQL Server having some columns, one of these columns (ID column and use sequential uniqueidentifier) should automatically populate its data when inserting other column data.
The values of the ID column should be generated automatically when insertion happens.
Please help me to do this, any help is appreciated.
NB: I am new to this step by step approach will be more helpful
Just create a table with a column ID of datatype uniqueidentifier and set it's default value to newsequentialid():
Then, when you go insert rows into that table, just omit the ID column from the list of columns you're inserted values into:
INSERT INTO dbo.YourTable(ColA, ColB, ....., ColX)
VALUES(.., .. ,. ...)
If you don't explicitly insert a value into ID, the default specification (newsequentialid()) will be used .
As per Marc_s's comment, you should use NEWSEQUENTIALID()
CREATE TABLE myTable (ColumnA uniqueidentifier DEFAULT NEWSEQUENTIALID());
See NEWSEQUENTIALID (Transact-SQL)
Good Morning. I have two tables, and one references the other. When I insert into the primary table, the primary key is auto-generated, viz Identity field. I need to insert this value into the second table.
I found out using the OUTPUT clause will give me the just inserted identity value, ans so I tried this.
insert into owners (pId)
insert into personal (firstName)
output inserted.pId
values ('fn')
It doesn't work though. I get an error:
Incorrect syntax near the keyword 'insert'
The personal table is the primary table, and the owners table contains the foreign key.
How can I do the required in SQL Server?
I've got stuck-up here for the past two days...
I think you just have your syntax slightly off - you can definitely take values inserted into the main table and use the OUTPUT clause to insert those into a secondary table.
INSERT INTO dbo.personal(firstName)
OUTPUT INSERTED.pId INTO dbo.owners(pId)
VALUES('fn')
This will insert a new row into personal and set the column firstName to fn. From that insert, the inserted row's identity column pId is then inserted into the other table, owners, as that table's pId column.
See the MSDN documentation on the OUTPUT clause for more details - you can either output any of the inserted values to the console (e.g. SQL Server Mgmt Studio), or you can output those values into a temporary or a permanent table.
Update: as 'dradu' has pointed out - this approach won't work in your case here, since the column in the owners table is part of a FK constraint (I had missed that point from your question). So you'll need to use some other way to do this - probably outputting the necessary information into a temporary table / table variable in your code
Try the following steps
1) Apply transaction level on insertion
2) Get last inserted id using Scope_Identity() function.
When you apply transaction level it will lock your tables and other/same user cannot insert the value in this time.
try this it will work for you.
Since OUTPUT clause cannot be used directly because of the foreign key, you could add the generated IDs into a temporary table, then insert those values into the owners table:
BEGIN TRANSACTION
CREATE TABLE #ids(ID INT)
INSERT INTO personal(firstName)
OUTPUT inserted.pid INTO #ids
SELECT 'A'
UNION SELECT 'B'
INSERT INTO owners(pid)
SELECT ID FROM #ids
COMMIT TRANSACTION
SCOPE_IDENTITY will work too, but it's limited to one value.
You can use the SCOPE_IDENTITY() function to return the identity value inserted.
DECLARE #id INT
INSERT INTO [Personal] (Colums ....) VALUES (this, that, stuff)
SET #id = SCOPE_IDENTITY()
INSERT INTO [Owners] (Colums ....) VALUES (#id ....)
I think Your option is to use SCOPE_IDENTITY() but the other closest to your option is IDENT_CURRENT(‘tablename’) so I thought, I post detail of detail of other identity options as well which might help you to understand your choice and might helpful some other time
##IDENTITY
It returns the last IDENTITY value produced on a connection, regardless of the table that produced the value, and regardless of the
scope of the statement that produced the value.
SCOPE_IDENTITY() It returns the last IDENTITY value produced on
a connection and by a statement in the same scope, regardless of the
table that produced the value.
IDENT_CURRENT(‘tablename’) It returns the last IDENTITY value
produced in a table, regardless of the connection that created the
value, and regardless of the scope of the statement that produced the
value.
Here is one simple example of using SCOPE_IDENTITY() to get recent Identity Value
http://msdn.microsoft.com/en-us/library/ms190315.aspx