Why does this TSQL fail? - tsql

IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name=N'isHidden' AND Object_ID=Object_ID(N'Templates'))
BEGIN
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Tmp_Templates
(
ID int NOT NULL IDENTITY (1, 1),
isHidden bit NULL,
FileName nvarchar(255) NOT NULL,
Name nvarchar(255) NOT NULL,
Description nvarchar(1024) NULL,
UploadedByTVDBUsersID int NOT NULL,
Created datetime NOT NULL
)
GO
SET IDENTITY_INSERT dbo.Tmp_Templates ON
GO
IF EXISTS(SELECT * FROM dbo.Templates)
EXEC('INSERT INTO dbo.Tmp_Templates (ID, FileName, Name, Description, UploadedByTVDBUsersID, Created)
SELECT ID, FileName, Name, Description, UploadedByTVDBUsersID, Created FROM dbo.Templates WITH (HOLDLOCK TABLOCKX)')
GO
SET IDENTITY_INSERT dbo.Tmp_Templates OFF
GO
DROP TABLE dbo.Templates
GO
EXECUTE sp_rename N'dbo.Tmp_Templates', N'Templates', 'OBJECT'
GO
ALTER TABLE dbo.Templates ADD CONSTRAINT
PK__Templates__499219E9 PRIMARY KEY CLUSTERED
(
ID
)
GO
PRINT N' Templates ADD isHidden'
COMMIT
END
Results in error:
Msg 102, Level 15, State 1, Line 7 Incorrect syntax near
'TRANSACTION'. Caution: Changing any part of an object name could
break scripts and stored procedures.
Update:
Excluding the IF statement wrapping the transaction this SQL is generated by Microsoft SQL Server Management Studio.
If I remove the wrapping IF statement then everything works, but I only need the change to happen if the field isn't already there. How can I make the IF statement work properly?
Um... why the -1 and the vote to close?

I had to wrap each part of the transaction in an IF statement so the GOs were not embedded in an IF statement. The following TSQL works just fine. The transaction updates the schema as expected.
BEGIN TRANSACTION
GO
IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name=N'isHidden' AND Object_ID=Object_ID(N'Templates'))
BEGIN
CREATE TABLE dbo.Tmp_Templates
(
ID int NOT NULL IDENTITY (1, 1),
isHidden bit NULL,
FileName nvarchar(255) NOT NULL,
Name nvarchar(255) NOT NULL,
Description nvarchar(1024) NULL,
UploadedByTVDBUsersID int NOT NULL,
Created datetime NOT NULL
)
ALTER TABLE dbo.Tmp_Templates ADD PRIMARY KEY (ID)
END
GO
IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name=N'isHidden' AND Object_ID=Object_ID(N'Templates'))
BEGIN
SET IDENTITY_INSERT dbo.Tmp_Templates ON
END
GO
IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name=N'isHidden' AND Object_ID=Object_ID(N'Templates'))
BEGIN
IF EXISTS(SELECT * FROM dbo.Templates)
EXEC('INSERT INTO dbo.Tmp_Templates (ID, FileName, Name, Description, UploadedByTVDBUsersID, Created)
SELECT ID, FileName, Name, Description, UploadedByTVDBUsersID, Created FROM dbo.Templates WITH (HOLDLOCK TABLOCKX)')
END
GO
IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name=N'isHidden' AND Object_ID=Object_ID(N'Templates'))
BEGIN
SET IDENTITY_INSERT dbo.Tmp_Templates OFF
END
GO
IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name=N'isHidden' AND Object_ID=Object_ID(N'Templates'))
BEGIN
DROP TABLE dbo.Templates
END
GO
IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name=N'isHidden' AND Object_ID=Object_ID(N'Templates'))
BEGIN
EXECUTE sp_rename N'dbo.Tmp_Templates', N'Templates', 'OBJECT'
PRINT N' Templates ADD isHidden'
END
GO
COMMIT

first GO statement split your query to
IF NOT EXISTS(SELECT * FROM SYS.COLUMNS WHERE Name=N'isHidden' AND Object_ID=Object_ID(N'Templates'))
BEGIN
BEGIN TRANSACTION
//error - END missing
And there is BEGIN keyword without END.
You need to remove GO statement.
UPDATE:
IF 1 = 1
BEGIN
SELECT * FROM someTable
GO
END
also generate Msg 102, Level 15, State 1, Line 3
Incorrect syntax near 'someTable'.

SqlServer won't allow you to use sp_rename inside the transaction since it could break things badly.
You can drop and add the table again, on in your case, you can also use a temporale table to do the query work, truncate the old table, and move rows from temp into Templates.
Sample temp table
CREATE TABLE #myTempTable
(
DummyField1 INT,
DummyField2 VARCHAR(20)
)
Reference
http://msdn.microsoft.com/en-us/library/ms188351.aspx

Related

.Net 6 Error on creation of TSQL trigger in Migration

Has anyone got a clue on how to address the following issue?
When attempting to update a database via migration I get the following error:
An explicit value for the identity column in table 'HistoryUsers' can only be specified when a column list is used and IDENTITY_INSERT is ON.
Running the trigger in Management studio works!
The code giving the error:
migrationBuilder.Sql(#"
CREATE TRIGGER [Users_TRIGGER]
ON [Users]
AFTER UPDATE, INSERT, DELETE
AS
DECLARE #EmpID int, #user nvarchar(max), #activity nvarchar(200);
IF EXISTS(SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
BEGIN
SET #activity = 'UPDATE';
SET #user = SYSTEM_USER;
INSERT INTO [HistoryUsers]
SELECT *, #activity, CURRENT_TIMESTAMP, #user
FROM inserted
END
IF EXISTS (SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted)
BEGIN
SET #activity = 'INSERT';
SET #user = SYSTEM_USER;
INSERT INTO [HistoryUsers]
SELECT *, #activity, CURRENT_TIMESTAMP, #user
FROM inserted
END
IF EXISTS(SELECT * FROM deleted) AND NOT EXISTS(SELECT * FROM inserted)
BEGIN
SET #activity = 'DELETE';
SET #user = SYSTEM_USER;
INSERT INTO [HistoryUsers]
SELECT *, #activity, CURRENT_TIMESTAMP, #user
FROM deleted
END
GO
");

PostgreSQL insert current sequence value to another field with condition

the issue:
i need to do something like this
drop table if exists tt_t;
create temp table tt_t(id serial primary key, main_id int, external_id int);
insert into tt_t(main_id, external_id)
select currval(pg_get_serial_sequence('tt_t', 'id')), 1
where not exists (select from tt_t where external_id = 1);
but execution raises an error
SQL Error [55000]: ERROR: currval of sequence "tt_t_id_seq" is not yet defined in this session
solution:
there is a way to solve this with anonymous code block
do
$$
begin
if not exists(select from tt_t where external_id = 1)
then
insert into tt_t(external_id, main_id)
values(1, currval(pg_get_serial_sequence('tt_t', 'id')));
end if;
end;
$$
;
but anonymous blocks has some restrictions e.g. Dapper parameters not working with PostgreSQL through npgsql connection, is postgres anonymous function parameterization supported?
how do i fix it without anonymous code block (UPD: and without any DDL changes)?
probable solution:
insert into tt_t(id, main_id, external_id)
select nextval(pg_get_serial_sequence('tt_t', 'id')), currval(pg_get_serial_sequence('tt_t', 'id')), 1
where not exists (select from tt_t where external_id = 1);
shorter code has been proposed to me
insert into tt_t(id, main_id, external_id)
select nextval(pg_get_serial_sequence('tt_t', 'id')), lastval(), 1
where not exists (select from tt_t where external_id = 1);
but i'm not sure if nextval will be calculated first
What about using a default value:
drop table if exists tt_t;
create temp table tt_t(id serial primary key, main_id int default lastval(), external_id int);
insert into tt_t(external_id)
select 1
where not exists (select * from tt_t where external_id = 1);
In theory it shouldn't be possible that another nextval() is called between the one for the id and the lastval(). However I am not 100% sure if there are some corner cases that I don't know of.
The following works as well (even if one or more of the external_id values already exist).
insert into tt_t(external_id)
select *
from (values (1),(2),(3)) x (external_id)
where not exists (select *
from tt_t
where external_id = x.external_id);

EF5 "the selected stored procedure or function returns no columns"

I am using EF 5 and this is my SP
USE [MYDatabase] GO
SET ANSI_NULLS ON GO
SET QUOTED_IDENTIFIER ON GO
ALTER PROCEDURE [dbo].[SP_FirstAttend] #serviceStart date, #serviceEnd date AS
BEGIN
SET NOCOUNT OFF
SET FMTONLY OFF
--IF (1=0)
--BEGIN
--SET FMTONLY ON
BEGIN
DROP TABLE #temp1
CREATE TABLE #temp1 (id int, sid int, npi int, fiscal int, serviceStart date, serviceEnd date, fcode varchar(10), tid int, StudName varchar(200), TherName varchar (200))
INSERT INTO #temp1
SELECT ID,
mand.SID,
mand.NPI,
FiscalYear,
ServiceStart,
ServiceEnd,
FundingCode,
ther.TID,
RTRIM(stud.StudentLastName) + ' ' + RTRIM(stud.StudentFirstName),
RTRIM(ther.LastName) + ' ' + RTRIM(ther.FirstName)
FROM MandateMaster AS mand
JOIN TherapistMaster AS ther ON ther.NPI = mand.NPI
JOIN StudentMaster AS stud ON stud.SID = mand.SID
SELECT *,
(SELECT top(1) sid
FROM SessionDetail
WHERE SID = tb1.sid
AND TID = tb1.tid) AS val1
FROM #temp1 AS tb1
WHERE ServiceStart >= #serviceStart
AND ServiceStart <= #serviceEnd;
END
-- END
END
and its still giving me "Stored procedure returns no columns".
I read somewhere to set the
integrated security=True; in the connection string on web.config but still nothing worked.
I been trying to find the solutions for this but keep getting the same message. Please let me know what to do .
Thanks.
You got nothing as result because this condition IF (1=0) always returns false then your select statement is never hit.
Just remove this IF (1=0) and your stored procedure will return some data.

T-SQL - populating data in temp table in stored procedure.

I need help with my stored procedure which I'm currently working on. Basically stored procedure works fine and gets me required data. I would like to keep this funcionality and add new temporary table within stored procedure and populate this temp table with the data that I get.
I don't know where/and how should I use INSERT INTO SELECT statement or SELECT INTO in my particular stored procedure.
Below I'm submiting my symplified stored procedure :
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_GetHourReportData]
#dateFrom SMALLDATETIME,
#dateTo SMALLDATETIME,
#hourFrom INT,
#hourTo INT
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE tempTable
(
-- fields
)
IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 0)
BEGIN
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
ELSE IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 1)
BEGIN
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
ELSE
BEGIN
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
END
Thanks. Any help will be appreciated.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_GetHourReportData]
#dateFrom SMALLDATETIME,
#dateTo SMALLDATETIME,
#hourFrom INT,
#hourTo INT
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #tempTable --notice the #
(
-- fields
)
IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 0)
BEGIN
insert into #tempTable
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
ELSE IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 1)
BEGIN
insert into #tempTable
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
ELSE
BEGIN
insert into #tempTable
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
END
END
CREATE TABLE tempTable
(
-- fields
)
IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 0)
BEGIN
INSERT INTO tempTable
(SELECT -- fields
FROM -- tables
WHERE -- conditions)
END
ELSE IF (DATEDIFF(DAY, #dateFrom, #dateTo) = 1)
BEGIN
INSERT INTO tempTable
(SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions)
END
ELSE
BEGIN
INSERT INTO tempTable
(SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions
UNION ALL
SELECT -- fields
FROM -- tables
WHERE -- conditions)
END
END
select * from tempTable

Is it possible to use local table variables in a procedure inside an sql query contained in a VARCHAR variable?

I have the following code:
DECLARE #temp_table_1 TABLE (id int identity(0, 1), col_1 varchar(50)),
#txtVar VARCHAR(MAX)
INSERT INTO #temp_table_1
SELECT col_1 FROM table_1 -- This table_1 is a real table in the database.
Set #txtVar = 'SELECT * FROM #temp_table_1'
EXECUTE (#txtVar)
The error I get is
Declare variable #temp_table_1.
How can I fix this?
Set #txtVar = 'SELECT * FROM myTable WHERE column_value=''' + #var1 + ''''
This article will help you get a basic ideas of dynamic sql.
EDIT
It is not possible to use table variables in a dynamic query.
You have to use temporary table or Use custom TABLE type.
Temporary table
CREATE TABLE #temp_table_1
(
id INT IDENTITY(0, 1),
col_1 VARCHAR(50)
)
DECLARE #txtVar VARCHAR(MAX)
INSERT INTO #temp_table_1
SELECT col_1
FROM table_1 -- This table_1 is a real table in the database.
SET #txtVar = 'SELECT * FROM #temp_table_1'
EXECUTE (#txtVar)
DROP TABLE #temp_table_1
Custom Table Type
CREATE TYPE DefaultTable AS TABLE (ID INT IDENTITY(0, 1), COL_1 VARCHAR(50))
GO
-- Fill a var of that type with some test data
DECLARE #MyTable DefaultTable
INSERT #MyTable
SELECT col_1 FROM table_1 -- This table_1 is a real table in the database.
-- Now this is how you pass that var into dynamic statement
EXECUTE sp_executesql N'SELECT * FROM #MyTable',
N'#MyTable DefaultTable READONLY',
#MyTable