I have a problem creating an index with the advantage database server if it doesn't exist with a sql query.
My query looks like this:
If not Exists(<SELECT Query for amount of indizes for one column>) then
Create Index Test on Tablename (No); endif
So I don't use FullTextSearchIndizes,because it is a integer field. Otherwhise it would look like this:
If not Exists(SELECT * FROM tablename WHERE CONTAINS( * , 'Test' )) then
Create Index Test on Tablename (Name) Content; endif
So, my only problem is how do I get the indices. I've read in other DBMS you can use sys.indexes and some other things.
Take a look at the System tables:
https://devzone.advantagedatabase.com/dz/webhelp/Advantage10/devguide_system_tables.htm
In particular there is a table called system.indexes:
https://devzone.advantagedatabase.com/dz/webhelp/Advantage10/master_system_indexes.htm
Try something more like this, utilizing the system commands. This is a working example I use on an Advantage Database:
IF (SELECT Name FROM system.indexes
WHERE Index_File_Name = 'GLDept.adi'
AND Index_Expression = 'DeptNumber') IS NULL
THEN
EXECUTE PROCEDURE sp_CreateIndex90(
'GLDept',
'GLDept.adi',
'DEPTNUMBER',
'DeptNumber',
'',
2051,
512,
'' );
END IF;
Related
I have a database FOO with several columns, among those I have one column "Url". I need to write a trigger before insert/update that will check the Url columns whether the newer value matches any existing values, i.e. "hello" except some predefined value. That means if "hello" is inserted or updated multiple times no error will happen otherwise it will check for duplicity. And if it finds some aborts the insertion update. This will also return some code so that my script calling for the insertion/update will know a failure has occurred. I know there might be other workarounds but I will need to have it this way. I am pretty new to SQL.
Foo {
Url
}
Here is the algorithm
Before update insert
if new value of Url is not "hello1" o "hello 2"
check if new value of Url already exists in Foo.Url if so abort otherwise allow update/insert
return something if aborted/success
try something like this.. you'll need to index your table..
IF EXISTS(SELECT URL FROM Foo.Url)
BEGIN
SELECT 'URL Exists Already'
END
ELSE
BEGIN
INSERT/UPDATE
END
A unique constraint wouldn't do what you want but you could create an instead of trigger with content something like as:
Create TRIGGER [dbo].[Trig_Insert_XXX]
ON [dbo].[XXX]
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO xxx ([url], field1, field2, fieldN)
SELECT [url], field1, field2, fieldN
FROM inserted i
WHERE i.url = 'hello' OR NOT EXISTS (SELECT * FROM xxx t2 WHERE t2.url = i.url);
END;
I suppose you're looking for a UNIQUE constraint & a CHECK constraint as
CREATE TABLE Foo(
Url VARCHAR(250) NOT NULL,
CONSTRAINT UQ_Url UNIQUE(Url),
CONSTRAINT CHK_Url CHECK (Url NOT IN ('hello1', 'hello2'))
);
See how it's working online.
If you are using SQL Server 2008 or newer version you can use MERGE as well, the syntax is like the following :
MERGE [TableName] AS TARGET
USING ( SELECT #UrlName ) AS SOURCE (UrlName) ON SOURCE.UrlName = TARGET.UrlName
WHEN MATCHED THEN
UPDATE SET ...
WHEN NOT MATCHED THEN INSERT ()
VALUES ();
Imagine that I have a table named "TableA" and this table has the columns "IDtable", "Tabname" and "Suffix".
IDtable and Tabname are correctly filled, but the suffix has all the records null.
I have to develop a stored procedure which allows to fill the Suffix column. For that, I know that I have to filter the name of the records in tabname.
Example:
Tabname: a_type_price
Suffix: price
Tabname: a_d_ser_sales
Suffix: sales
I think that I have to develop a for cycle, which looks for the " _ " in the names of Tabname and filters everything after the last " _ ".
Anyone have any idea of the best way to perform this stored procedure?
You'll want to update the table - you don't even really need a stored procedure unless this is something you ahve to run as a job or frequently.
You could do so like this:
CREATE PROCEDURE usp_Upd_TableASuffix()
AS
BEGIN
SET NOCOUNT ON
UPDATE TableA SET Suffix = RIGHT(Tabname, CHARINDEX('_', REVERSE(Tabname)) - 1)
END
Quick explanation of that: You want the RIGHT part of the string after the last _ character - to get the last one, use CHARINDEX on the REVERSE of the string.
You can't do this with a default constraint since you'd have to reference another column, but you could use a trigger, assuming IDtable is your primary key:
CREATE TRIGGER trg_TableA_Suffix
ON TableA
AFTER INSERT, UPDATE
AS
UPDATE TableA SET Suffix = RIGHT(i.Tabname, CHARINDEX('_',REVERSE(i.Tabname))-1)
FROM inserted i
WHERE TableA.IDTable = i.IDTable
GO
Note that this won't work if IDTable is non-unique, or if your table lacks a primary key entirely.
One last option - and this is probably the best if you really want Suffix to only ever contain the last part of Tabname and never want to change it - you could make Suffix a computed column.
ALTER TABLE TableA DROP COLUMN Suffix
ALTER TABLE TableA ADD Suffix AS RIGHT(Tabname, CHARINDEX('_',REVERSE(Tabname))-1) PERSISTED
For informix.
As #dan-field said, and explain, you can do the update using:
UPDATE tablea
SET suffix = RIGHT(tabname, CHARINDEX('_', REVERSE(tabname)) - 1);
Another way is:
UPDATE tablea
SET suffix = SUBSTR(tabname, INSTR(tabname, '_', -1)+1);
INSTR will give you the index of the first occurrence from the right (-1) of ''. SUBSTR will give you the substring starting from the index you pass, in this case we add 1 because we don't want the '' to be outputted.
Bear in mind that RIGHT, CHARINDEX, REVERSE and INSTR functions are only available from 11.70 onward.
On 11.50 you can try this ugly solution:
CREATE PROCEDURE test()
DEFINE i_IDtable LIKE tablea.IDtable;
DEFINE c_suffix LIKE tablea.tabname;
DEFINE i INT;
FOREACH cur1 WITH HOLD FOR
SELECT IDtable ,Tabname
INTO i_IDtable, c_suffix
FROM tablea
LET i = LENGTH(c_suffix);
WHILE i > 0
IF SUBSTR(c_suffix,i) LIKE '\_%' THEN
LET c_suffix = SUBSTR(c_suffix,i+1);
EXIT WHILE;
ELSE
LET i = i -1;
END IF
END WHILE;
UPDATE tablea
SET suffix = c_suffix,
WHERE idtable = i_IDtable;
END FOREACH;
END PROCEDURE;
But if suffix is always this part of the tabname it's not a good practice to store on the table.
You can easily get it from the already stored tabname. And even programmatically is easy to deal with it.
I have a check box on front end.
If the check box is checked: data with only checked chk1 should appear on front end.
If the check box is not checked: full data should appear on front end.
Please suggest how should I proceed with the same in SQL Using If else / Case statement.
I am using:
SELECT *
FROM table1
where (some conditions) AND
CASE #a.Id_Oem_Irm
WHEN 0 THEN (a.id_oem_irm in(0,1))
WHEN 1 THEN (a.id_oem_irm in (1))
END
PS: a.Id_Oem_Irm: a is the table name, Id_oem_irm is the column name for check box.
I would recommend writing this as:
where (some conditions) AND
((#a.Id_Oem_Irm = 0 and a.id_oem_irm in(0, 1)) OR
(#a.Id_Oem_Irm = 1 and a.id_oem_irm in (1) )
)
I am not sure what #a.Id_Oem_Irm is supposed to be. I suspect you want a variable there.
Or you could tune it a bit like this:
SELECT *
FROM table1
where (some conditions) AND
(a.id_oem_irm = 1 OR
#a.Id_Oem_Irm = 0)
This is only valid if #a.Id_Oem_Irm is always 0 or 1. Otherwise, you obviously should add a #a.Id_Oem_Irm IN (0,1) or <= 1 (if it can't be negative) condition.
What is a? The alias for another table you didn't include here?
The simpler way to do this is create a storedprocedure which will take the input "#a.Id_Oem_Irm"
Example:
CREATE PROCEDURE p_get_a_data(
IN Id INT(1)
)
BEGIN
IF (Id = 0) BEGIN
--YOur query to retrieve partiular row/ column
END;
IF(Id = 1) BEGIN
--YOur query to retrieve all data
SELECT * FROM table1
where (some conditions)
END;
END
The usage of stored procedure will give you selected data and the query is precompiled in the database so it faster.
Note: I didn't quite understand what your query is returning so replace mine with yours
I'm trying to write a small script to create a database if it doesn't exist, and create a table for that database if the table doesn't exist. What I have is this:
IF (db_id('db') is null) BEGIN
print 'Must create the database!';
CREATE DATABASE db;
END
USE db;
IF (object_id('test_table', 'U') is null) BEGIN
print 'Must create the table!';
CREATE TABLE test_table (
id int
);
END
I'm getting a strange error with this:
Database 'db' does not exist. Make sure that the name is entered correctly.
I'm guessing that it's parsing the script before running it and finding that 'db' doesn't exist, so it can't use it.
There must be a solution to this. Any help is appreciated.
SOLVED!
I realised 5 minutes after posting that the GO keyword solves the problem. Here is the fixed code:
IF (db_id('db') is null) BEGIN
print 'Must create the database!'
CREATE DATABASE db;
END
GO
USE db
IF (object_id('test_table', 'U') is null) BEGIN
print 'Must create the table!';
CREATE TABLE test_table (
id int
);
END
Sorry for wasting everyone's time.
SQL statements are parsed as one batch unless you break them apart. In SQL Server, you can use GO to do this. In both MySQL and SQL Server, you can use BEGIN and END.
If you want to commit the separate blocks to the database in different instances you can use BEGIN TRANS / COMMIT TRANS and START TRANSACTION / COMMIT for SQL Server and MySQL, respectively.
Something along the lines of Check if table exists in SQL Server would probably work (With a slight change)
IF (NOT EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'TheSchema'
AND TABLE_NAME = 'TheTable'))
BEGIN
--Do Stuff
END
I might suggest using the built-in SQL syntax -
CREATE DATABASE name IF NOT EXISTS;
And subsequently
CREATE TABLE name(definition) IF NOT EXISTS;
If I try to execute the following code, I get the errors
Msg 207, Level 16, State 1, Line 3 Invalid column name 'Another'. Msg
207, Level 16, State 1, Line 4 Invalid column name 'Another'.
even though the predicate for both IF statements always evaluates to false.
CREATE TABLE #Foo (Bar INT)
GO
IF (1=0)
BEGIN
SELECT Another FROM #Foo
END
GO
IF (1=0)
BEGIN
ALTER TABLE #Foo ADD Another INT
SELECT Another FROM #Foo
END
GO
DROP TABLE #Foo
This is probably over-simplified for the sake of the example; in reality what I need to do is select the values from a column, but only if the column exists. If it doesn't exist, I don't care about it. In the problem that drove me to ask this question, my predicate was along the lines of EXISTS (SELECT * FROM sys.columns WHERE object_id = #ID AND name = #Name). Is there a way to achieve this without resorting to my arch-enemy Dynamic SQL? I understand that my SQL must always be well-formed (i.e. conform to grammar) - even within a block that's never executed - but I'm flabbergasted that I'm also being forced to make it semantically correct too!
EDIT:
Though I'm not sure the code below adds much to the code above, it's a further example of the problem. In this scenario, I only want to set the value of Definitely (which definitely exists as a column) with the value from Maybe (which maybe exists as a column) if Maybe exists.
IF EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('dbo.TableName', 'U') AND name = 'Maybe')
BEGIN
UPDATE dbo.TableName SET Definitely = Maybe
END
SQL Server doesn't execute line by line. It isn't procedural like .net or Java code. So there is no "non-executed block"
The batch is compiled in one go. At this point, the column doesn't exist but it knows the table will be. Table does not have a column called "Another". Fail.
Exactly as expected.
Now, what is the real problem you are trying to solve?
Some options:
2 tables or one table with both columns
use Stored procedures to decouple scope
not use temp tables (maybe not needed; it could be your procedural thinking...)
dynamic SQL (from Mitch's deleted answer)
Edit, after comment;
Why not hide schema changes behind a view, rather than changing all code to work with columns that may/may not be there?
You can use EXEC to handle it. It's not really dynamic SQL if the code never actually changes.
For example:
CREATE TABLE dbo.Test (definitely INT NOT NULL)
INSERT INTO dbo.Test (definitely) VALUES (1), (2), (3)
IF EXISTS (SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.Test', 'U') AND
name = 'Maybe')
BEGIN
EXEC('UPDATE dbo.Test SET definitely = maybe')
END
SELECT * FROM dbo.Test
ALTER TABLE dbo.Test ADD maybe INT NOT NULL DEFAULT 999
IF EXISTS (SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.Test', 'U') AND
name = 'Maybe')
BEGIN
EXEC('UPDATE dbo.Test SET definitely = maybe')
END
SELECT * FROM dbo.Test
DROP TABLE dbo.Test
You can also try Martin Smith's "Workaround" using a non-existing table to get "deferred name resolution" for columns.
I had the same issue.
We are creating a script for all changes for years and this is the first time that we have this issue.
I've tried all your answers and didn't find the issue.
In my case it was because of temporary table within the script that I'm using also within a stored procedure, although every sentence has go.
I've found that if I'm adding if exists with drop to the temporary table after the script is using the temporary table, it is working correctly.
Best regards,
Chen
Derived from the answer by #gbn.
What i did to solve the issue was to use 'GO' between the ALTER query and the query that uses the column added by ALTER. This will make the 2 queries to be run as separate batches thereby ensuring your 'Another' column is there before the SELECT query.