SQL Server stored procedure/cursor - sql

I have a list of 20 spatial tables (Zoom1-Zoom20) and from time invalid geometry pops up in these tables. When the invalid geometry occurs I run the following statement to find where the invalid geometry is:
SELECT ID FROM Zoom10 WhERE Location.STIsValid() = 0
Typically I have to run the above statement for every Zoom table (the error that leads to the invalid geometry does not indicate which zoom table has invalid geometry) and when a result is returned from the select statement I run the following statement to correct the geometry:
UPDATE MGeoZoom10 set Location = Location.MakeValid() where Location.STIsValid() = 0
My question is can this process be automated with a stored procedure that gets the list of zoom tables
select name from sys.tables where name like '%zoom'
and then loops through the zoom tables with
SELECT ID FROM Zoom10 WhERE Location.STIsValid() = 0
and if a result is returned it runs the update statement on the zoom table?

Try this:
sp_msforeachtable '
if ''?'' Like ''%Zoom%''
Begin
If Exists(SELECT ID FROM ? WhERE Location.STIsValid() = 0)
UPDATE ? set Location = Location.MakeValid() where Location.STIsValid() = 0
End
'

Do you have 2 UDFs called STIsValid and MakeValid? If so, you could do something like this...
SELECT id INTO #Processed FROM Sysobjects WHERE name = '(no such table)'
DECLARE #TableId int, #TableName varchar(255), #CorrectionSQL varchar(255)
SELECT #TableId = MIN(id) FROM Sysobjects WHERE type = 'U' AND name LIKE '%zoom'
AND id NOT IN (SELECT id FROM #Processed)
SET #TableId = ISNULL(#TableId, -1)
WHILE #TableId > -1 BEGIN
PRINT #TableId
SELECT #TableName = name FROM Sysobjects WHERE type = 'U' AND id = #TableId
SET #CorrectionSQL = 'UPDATE ' + #TableName + ' SET Location = dbo.MakeValid(Location) where dbo.STIsValid(Location) = 0'
PRINT #CorrectionSQL
EXEC(#CorrectionSQL)
INSERT INTO #Processed (id) VALUES(#TableId)
SELECT #TableId = MIN(id) FROM Sysobjects WHERE type = 'U' AND name IN ('DimAccount', 'DimCurrency', 'DimCustomer')
AND id NOT IN (SELECT id FROM #Processed)
END

Related

SQL: SAP Hana if parameter is null, ignore where

I'm passing 3 parameters into my Hana Stored Procedure to use as WHERE clauses, and if the parameter is null, I want the procedure to behave as though that condition doesn't exist.
example:
if one of the input parameters is deviceType.
SELECT TOP 5 DISTINCT USERS FROM MYTABLE
WHERE USERDEVICE = deviceType;
if deviceType is null, query should simply be
SELECT TOP 5 DISTINCT USERS FROM MYTABLE.
I know I can achieve this with if statements, but is there another way to do it?
Basically, the requirement is to not apply any condition is deviceType IS NULL. Instead of altering the query dynamically, you could just construct a condition that always returns true in such a situation by using the logical or operator:
SELECT TOP 5 DISTINCT USERS
FROM MYTABLE
WHERE deviceType IS NULL OR USERDEVICE = deviceType;
When using SQLScript you can use the APPLY_FILTER() function.
E.g.
drop procedure getTopUsers;
create procedure getTopUsers (IN filter_cond NVARCHAR(200)) as
begin
vUsers = SELECT DISTINCT user_name, creator FROM USERS;
if (:filter_cond is NULL) then
TopUsers = select TOP 5 user_name FROM :vUsers;
else
tTopUsers = APPLY_FILTER(:vUsers, :filter_cond);
TopUsers = SELECT TOP 5 user_name FROM :tTopUsers;
end if;
SELECT user_name FROM :TopUsers;
end;
call getTopUsers ('CREATOR != ''SYS'' ');
call getTopUsers (NULL);
DECLARE #deviceType VARCHAR(100)
DECLARE #SQL VARCHAR(256)
,#sql1 VARCHAR(256) = 'WHERE USERDEVICE = ''' + #deviceType + ''''
SET #SQL = 'SELECT TOP 5 DISTINCT USERS FROM MYTABLE'
SET #SQL = CASE
WHEN #deviceType IS NULL
THEN #SQL
ELSE #SQL + ' ' + #sql1
END
EXEC (#SQL)

How to use SQL column name only if the column exists?

I've been trying to get a textual result from CASE(def.OPTION_CATEGORY_ID) in a select, but I'm having a hard time implementing the terms.
What I'm trying to do is to check if OPTION_CATEGORY_ID is an existing column in sys.columns. If it is then I'm trying to make the int to text translation using the When - Then on the bottom but the SQL is not aware of the column name so CASE(def.OPTION_CATEGORY_ID) is failing because the column name is invalid.
Is there any way to call def.OPTION_CATEGORY_ID using an alias name so the SQL won't fail it before hand?
Thanks
SELECT DISTINCT *
FROM
(SELECT def.OPTION_DEF_ID AS 'Def ID',
ass.ASSET_NAME AS 'Asset Name',
CASE(def.OPTION_TYPE_ID)
WHEN 1 THEN 'A'
WHEN 2 THEN 'B'
END AS 'Option Type',
case when exists (SELECT name
FROM sys.columns
WHERE Name = 'OPTION_CATEGORY_ID'
AND Object_ID = Object_ID(N'TFC_OPTION_DEFINITION'))
then
-- Column Exists
CASE(def.OPTION_CATEGORY_ID)
WHEN 1 THEN 'C'
WHEN 2 THEN 'D'
WHEN 3 THEN 'E'
WHEN 4 THEN 'F'
end
End AS 'test' ,
-- the rest of the select
If you want to select a column and you are not sure if it exists, you cannot write it explicitly in your code, and expect it to compile.
You should build the statement dynamically based on the run time information of which the column exists or not:
DECLARE #statement VARCHAR(MAX)
IF((SELECT COUNT(*)
FROM sys.columns
WHERE Name = 'OPTION_CATEGORY_ID'
AND Object_ID = Object_ID(N'TFC_OPTION_DEFINITION')) > 0)
BEGIN
SET #statement = --assign a query which uses OPTION_CATEGORY_ID
END
ELSE
BEGIN
SET #statement = --assign a query which does not use OPTION_CATEGORY_ID
END
EXEC sp_executesql #statement

Sql if statement after another if check

I'm working with Microsoft SQL Server.
IF EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'ServerSettings'
AND COLUMN_NAME = 'MapIsAlwayCalcLenByWebServices'
)
IF (
SELECT MapIsAlwayCalcLenByWebServices
FROM ServerSettings
) = 0
UPDATE ServerSettings
SET MapCalculateDistanceSource = 0
Does anybody know why this code throw the error "Invalid column name". I thought that second select execute only when the first if is true.
No, the entire batch is first compiled, and then execution starts. Since it can't compile the batch because you reference an invalid column, it never executes the if statement.
You would need to protect the code that references a possibly absent column in an EXEC, something like:
if exists(select * from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'ServerSettings' and
COLUMN_NAME = 'MapIsAlwayCalcLenByWebServices')
begin
exec('UPDATE ServerSettings SET MapCalculateDistanceSource = 0
WHERE MapIsAlwayCalcLenByWebServices = 0')
end
Try this one -
IF EXISTS(
SELECT 1
FROM sys.columns c
WHERE c.name = 'MapIsAlwayCalcLenByWebServices'
AND c.[object_id] = OBJECT_ID('dbo.ServerSettings')
) BEGIN
EXEC sys.sp_executesql '
UPDATE dbo.ServerSettings
SET MapCalculateDistanceSource = 0
WHERE MapIsAlwayCalcLenByWebServices = 0'
END
Another way to check the existing column
IF COL_LENGTH('dbo.ServerSettings', 'MapIsAlwayCalcLenByWebServices') IS NOT NULL
EXEC ('UPDATE dbo.ServerSettings
SET MapCalculateDistanceSource = 0
WHERE MapIsAlwayCalcLenByWebServices = 0')

TSQL: Using a Table in a Variable in a Function

I'm trying to do a select from a table that will need to be in a variable. I'm working with tables that are dynamically created from an application. The table will be named CMDB_CI_XXX, where XXX will be an integer value based on a value in another table. The ultimate goal is to get the CI Name from the table.
I've tried passing the pieces that make up the table name to a function and string them together and then return the name value, but I'm not allowed to use an EXEC statement in a function.
This is what I want to execute to get the name value back:
Select [Name] from 'CMDB_CI_' + C.CI_TYPE_ID + Where CI_ID = c.CI_ID
This is the code in the SP that I'd like to use the function in to get the name value:
SELECT
CI_ID,
C.CI_TYPE_ID,
CI_CUSTOM_ID,
STATUS,
CI_TYPE_NAME,
--(Select [Name] from CMDB_CI_ + C.CI_TYPE_ID + Where CI_ID = c.CI_ID)
FROM [footprints].[dbo].[CMDB50_CI_COMMON] c
join [footprints].[dbo].[CMDB50_CI_TYPE] t
on c.CI_TYPE_ID = t.CI_TYPE_ID
where status <> 'retired'
order by CI_TYPE_NAME
I'm not sure what to do with this. Please help?
Thanks,
Jennifer
-- This part would be a SP parameter I expect
DECLARE #tableName varchar(100)
SET #tableName = 'CMDB_CI_508'
-- Main SP code
DECLARE #sqlStm VARCHAR(MAX)
SET #sqlStm = 'SELECT *
FROM '+ #tableName
EXEC (#sqlStm)
Fiddle http://sqlfiddle.com/#!3/436a7/7
First off, yes, I know it's a bad design. I didn't design it. It came with the problem tracking software that my company bought for our call center. So I gave up altogether on the approach I was going for and used a cursor to pull all the the names from the various tables into one temp table and then used said temp table to join to the original query.
ALTER Proc [dbo].[CI_CurrentItems]
As
Declare #CIType nvarchar(6)
Declare #Qry nvarchar(100)
/*
Create Table Temp_CI
( T_CI_ID int,
T_CI_Type_ID int,
T_Name nvarchar(400)
)
*/
Truncate Table Temp_CI
Declare CI_Cursor Cursor For
select distinct CI_TYPE_ID FROM [footprints].[dbo].[CMDB50_CI_COMMON]
where STATUS <> 'Retired'
Open CI_Cursor
Fetch Next from CI_Cursor into #CIType
While ##FETCH_STATUS = 0
BEGIN
Set #Qry = 'Select CI_ID, CI_Type_ID, Name from Footprints.dbo.CMDB50_CI_' + #CIType
Insert into Temp_CI Exec (#Qry)
Fetch Next from CI_Cursor into #CIType
END
Close CI_Cursor
Deallocate CI_Cursor
SELECT CI_ID,
C.CI_TYPE_ID,
CI_CUSTOM_ID,
STATUS,
CI_TYPE_NAME,
T_Name
FROM [footprints].[dbo].[CMDB50_CI_COMMON] c
JOIN [footprints].[dbo].[CMDB50_CI_TYPE] t
ON c.CI_TYPE_ID = t.CI_TYPE_ID
JOIN Temp_CI tc
ON c.CI_ID = tc.T_CI_ID
AND t.CI_TYPE_ID = tc.T_CI_TYPE_ID
WHERE STATUS <> 'retired'
ORDER BY CI_TYPE_NAME

SQL: How to use a column that was just added

I am trying to add 2 columns and then I would like to set some values to them but I get a compile-error saying the column does not exist. I am using the following script:
IF #LogProcessed = 0
Begin
IF NOT EXISTS (select column_name from INFORMATION_SCHEMA.columns where table_name = 'SYSTM_FRM' and column_name = 'SF_Ip_TXT')
ALTER TABLE SYSTM_FRM add SF_Ip_TXT NVARCHAR(20)
IF NOT EXISTS (select column_name from INFORMATION_SCHEMA.columns where table_name = 'SYSTM_FRM' and column_name = 'SF_Port_NUM')
ALTER TABLE SYSTM_FRM add SF_Port_NUM int
IF (EXISTS (select column_name from INFORMATION_SCHEMA.columns where table_name = 'FRM' and column_name = 'FRM_Ip_TXT') AND
EXISTS (select column_name from INFORMATION_SCHEMA.columns where table_name = 'FRM' and column_name = 'FRM_Ip_TXT'))
begin
Update dbo.SYSTM_FRM
SET dbo.SYSTM_FRM.SF_Ip_TXT = dbo.FRM.FRM_Ip_TXT,
dbo.SYSTM_FRM.SF_Port_NUM = dbo.FRM.FRM_Port_NUM
FROM dbo.FRM INNER JOIN dbo.SYSTM_FRM ON dbo.FRM.FRM_RCRD_NUM = dbo.SYSTM_FRM.SF_FrameRecord_NUM
ALTER TABLE FRM DROP COLUMN FRM_Ip_TXT
ALTER TABLE FRM DROP COLUMN FRM_Port_NUM
end
Update [Update_Log]
Set Update_Log_Processed = 1
Where [Update_Log_Version] = '00001'
end
Is there any way to use a column that I am adding in the same script?
you cannot save it in a proc like that
example
create table TestAdd2 (id int)
go
You cannot create this procedure
create proc prTest as
insert TestAdd2 values (1)
exec ('ALTER TABLE TestAdd2 add SF_Port_NUM int')
update TestAdd2 set id = 1,SF_Port_NUM = 2
select * from TestAdd2
GO
You get this error
Msg 207, Level 16, State 1, Procedure prTest, Line 7
Invalid column name 'SF_Port_NUM'.
This is because at parse time the column does not exist
However if you use dynamic SQL for the update you are good to go
create proc prTest2 as
insert TestAdd2 values (1)
exec ('ALTER TABLE TestAdd2 add SF_Port_NUM int')
exec ('update TestAdd2 set id = 1,SF_Port_NUM = 2')
select * from TestAdd2
GO
in your case your update statement would be
exec('Update dbo.SYSTM_FRM
SET dbo.SYSTM_FRM.SF_Ip_TXT = dbo.FRM.FRM_Ip_TXT,
dbo.SYSTM_FRM.SF_Port_NUM = dbo.FRM.FRM_Port_NUM
FROM dbo.FRM INNER JOIN dbo.SYSTM_FRM
ON dbo.FRM.FRM_RCRD_NUM = dbo.SYSTM_FRM.SF_FrameRecord_NUM')
Put a GO in between
All DDL statements should follow the statement seperator GO in order to make use of it