Stored Procedure consist Add column, Update data for that column, and Select all data from that table - sql

I've written a stored procedure as following:
CREATE PROC spSoNguoiThan
#SNT int
AS
begin
IF not exists (select column_name from INFORMATION_SCHEMA.columns where
table_name = 'NhanVien' and column_name = 'SoNguoiThan')
ALTER TABLE NhanVien ADD SoNguoiThan int
else
begin
UPDATE NhanVien
SET NhanVien.SoNguoiThan = (SELECT Count(MaNguoiThan)FROM NguoiThan
WHERE MaNV=NhanVien.MaNV
GROUP BY NhanVien.MaNV)
end
SELECT *
FROM NhanVien
WHERE SoNguoiThan>#SNT
end
GO
Then I get the error :
Server: Msg 207, Level 16, State 1, Procedure spSoNguoiThan, Line 12
Invalid column name 'SoNguoiThan'.
Server: Msg 207, Level 16, State 1, Procedure spSoNguoiThan, Line 15
Invalid column name 'SoNguoiThan'.
Who can help me?
Thanks!

When the stored proc is parsed during CREATE the column does not exist so you get an error.
Running the internal code line by line works because they are separate. The 2nd batch (UPDATE) runs because the column exists.
The only way around this would be to use dynamic SQL for the update and select so it's not parsed until EXECUTE time (not CREATE time like now).
However, this is something I really would not do: DDL and DML in the same bit of code

I ran into this same issue and found that in addition to using dynamic sql I could solve it by cross joining to a temp table that had only one row. That caused the script compiler to not try to resolve the renamed column at compile time. Below is an example of what I did to solve the issue without using dynamic SQL
select '1' as SomeText into #dummytable
update q set q.ValueTXT = convert(varchar(255), q.ValueTXTTMP) from [dbo].[SomeImportantTable] q cross join #dummytable p

Related

How to make a query replace column if exist using sql-server query

I have a query as the below one:
alter table [toolDB].[dbo].[esn_sho] add esn_umts_sho_relation_key as Convert(nvarchar(50),[utrancell])+'_'+Convert(nvarchar(50),[utranrelation])
So All I need I want to replace esn_umts_sho_relation_key column if exist...
As I got this error:
[Microsoft][SQL Server Native Client 11.0][SQL Server]Column names in each table must be unique. Column name 'esn_umts_sho_relation_key' in table 'toolDB.dbo.esn_sho' is specified more than once
I tired to use the below code but it's doen't work:
IF NOT EXISTS (alter table [toolDB].[dbo].[esn_sho] add esn_umts_sho_relation_key as Convert(nvarchar(50),[utrancell])+'_'+Convert(nvarchar(50),[utranrelation]))
It gives me this error:
Incorrect syntax near the keyword 'alter'.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ')'
So I want to add If Exist in this query any one knows how to solve this prolem...
The column I already exist in the table ,but I want to replace it if exist to escape from this error...
IF COL_LENGTH('TableName', 'ColumnName') IS NOT NULL
BEGIN
-- Column Exists
-- here you can put your cond...
END
IF COL_LENGTH('[toolDB].[dbo].[esn_sho]', 'esn_umts_sho_relation_key') IS NOT NULL
BEGIN
-- Column Exists
alter table [toolDB].[dbo].[esn_sho] add esn_umts_sho_relation_key as Convert(nvarchar(50),[utrancell])+'_'+Convert(nvarchar(50),[utranrelation])---Put your condition in proper way...
END
IF EXISTS(SELECT * FROM DatabaseName where ColumnName = #YourParameter)
BEGIN
You Can Write Alter Query Here
END
ELSE
BEGIN
You Can Set Here AN Else Condition/Optional
END
To solve this particular issue, you can use the system tables. Try this
SELECT *
FROM sys.all_objects obj
JOIN sys.all_columns col ON obj.object_id = col.object_id
WHERE
obj.Name = #YourTableName
AND col.Name = #YourColumnName
This will give you the columns in your table if it exists. You can use this to make your decision about what you would do if it exists/doesn't exist.

How to create a stored procedure to copy data from a query to a temporary table?

I have need of inserting data to a temporary table from an existing table/query. The following produces the error detailed below.
CREATE TABLE SPTemporary
AS
BEGIN
SELECT * into #temppT
FROM SampleTable
END
Throws this error:
Msg 156, Level 15, State 1, Line 3
Incorrect syntax near the keyword 'begin'.
Correct your syntax, use procedure instead of table :
create procedure SPTemporay
as
begin
select * into #temppT
from SampleTable
end
However, if you want only copy of data then only subquery is enough :
select st.* into #temppT
from SampleTable st
One method is:
select st.*
into SPTemporay
from SampleTable st
One select can only put data in one table. It is unclear which one you really want SPTemporary or #temppT. You can repeat the select if you really need the same data in two tables.
EDIT:
If you want a stored procedure, you could do:
create procedure SPTemporay
as begin
select *
into #temppT
from SampleTable
end;
This is rather non-sensical, because the temporary table is discarded when the stored procedure returns.
I think the syntax is wrong, it should be like that:
create table SPTemporay
as
select * from SampleTable
I hope this helps.

SQL Code Evaluation stopping a valid transaction

As part of the company I am working for at the moment I need to create some database upgrade scripts to replace some work of a previous contractor.
The code before the following block runs, creates the new ID column, and then this script looks to populate the values and then drop some columns.
IF EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(N'[Central].[Core.Report].[ReportLessonComp]')
AND name = 'Name')
and
EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(N'[Central].[Core.Report].[ReportLessonComp]')
AND name = 'Code')
BEGIN
UPDATE
[Central].[Core.Report].[ReportLessonComp]
SET
CompetencyId = rc.Id
FROM
[Central].[Core.Report].[ReportLessonComp] rlc
INNER JOIN
[Core.Lookup].ReportCompetency rc
ON
rc.Code = rlc.Code and rc.Name = rlc.Name
ALTER TABLE [Central].[Core.Report].[ReportLessonComp] DROP COLUMN CODE
ALTER TABLE [Central].[Core.Report].[ReportLessonComp] DROP COLUMN [Name]
ALTER TABLE [Central].[Core.Report].[ReportLessonComp] DROP COLUMN [Description]
END
GO
When running the if exists \ not exists checks and then select getdate() this works perfeclty fine and gives me the result I expect.
However, when I run the code block above I get error
Msg 207, Level 16, State 1, Line 23
Invalid column name 'Code'.
Msg 207, Level 16, State 1, Line 23
Invalid column name 'Name'.
This script it part of a larger upgrade script and is used in a system calle RoundHouse https://github.com/chucknorris/roundhouse which is the system chosen by the company.
Prior to the above if exists check,
IF (SELECT COUNT(1) FROM sys.columns
WHERE OBJECT_ID = OBJECT_ID('[Central].[Core.Report].[ReportLessonComp]')
AND Name in ('Name','Code')) = 2
which also gave the same issue. I have five tables that I need to update and this is going to stop the team from working if I cant resolve this at my next PR
What can I do in order to stop this from causing the upgrade scripts to fail?
EDIT -- The reason I am linking on varchar fields also is because the previous developer did not create relationships between tables, and was just inserting strings into tables rather than relating by ID causing the potential for unlinked \ inconsistent data.
The table edit prior to this creates the new id column, and this script is getting the value and dropping columns that are no longer needed
SQL Server will parse the whole of the statement prior to execution, so the exists check does not protect you from the update being parsed. If the column has already been dropped, that makes the statement invalid and you get a parse error. The update statement would have to be executed as dynamic SQL, sp_execute basically so that the varchar of the update is not directly parsed.
For SQL Server 2016 and above the drop column can be protected a bit more as well:
ALTER TABLE [Central].[Core.Report].[ReportLessonComp] DROP COLUMN IF EXISTS CODE

using new columns in the temp table added by alter table not work

I have a problem that the new added column can't be used in the further comments.
I have a temp table built by "select into" then I need to add an identity column by "alter table". But when I want to use the new column in a "join", I got an error "Invalid column". please note that, these commands could work separately.
I think the reason is, the new column is not found by the compiler and it give an error before running it.
Is there a solution for that ?
I have got this problem in sql server 2000 and it seems in a newer version, the problem is not there.
create table #tmp_tb
(name varchar(4), val int)
insert into #tmp_tb values('ab',1);
insert into #tmp_tb values('abc',2);
select * from #tmp_tb
alter table #tmp_tb add id int NOT NULL IDENTITY(1,1);
select * from #tmp_tb
select id,name,val from #tmp_tb
An error occurred :
Msg 207, Level 16, State 3, Line 9
Invalid column name 'id'.
Replace the last line with
EXECUTE sp_executesql N'select id,name,val from #tmp_tb';
Indeed, the parser doesn't know about the new column yet. By passing it through sp_executesql you avoid this.

Create trigger error: 'Incorrect Syntax near 'dbo'

I'm currently learning some regarding SQL triggers. I am trying to create a column on a test table which will show the current date when the row is updated. The column datatype is type DateTime So far I have:
CREATE TRIGGER lastUpdated
ON [dbo].[ImportTest]
AFTER UPDATE
AS
BEGIN
IF NOT UPDATE(LAST_UPD)
BEGIN
SET [dbo].[ImportTest].[LAST_UPD] = CURRENT_TIMESTAMP
END
END
GO
However, I get the following error trying to execute:
Msg 102, Level 15, State 1, Procedure lastUpdated, Line 29
Incorrect syntax near 'dbo'.
Any help would be appreciated.
You cannot update a column like assigning value to variable. Try this
IF NOT UPDATE(LAST_UPD)
BEGIN
UPDATE IT
SET [LAST_UPD] = CURRENT_TIMESTAMP
FROM [dbo].[ImportTest] IT
WHERE EXISTS (SELECT 1
FROM inserted i
WHERE i.somecol = it.somecol
And ...)
END