How to add brackets in heading of a table column in database? - sql

I want to create a database containing multiple tables using postgres 11 and i'm currently creating a table which contain brackets in the heading of the column (as shown as follows).
Table - supp_details
supp_id|supp_name | supp_weight(Kg)|
Can i add units to the heading and what is the proper way to do so with sql?
I'm a fresher to query writing, so please help me with this.

You could place the column name in quotes, e.g. use "supp_weight(Kg)", but it is best to avoid placing special characters or keywords as object names. Instead, I suggest using the following name:
supp_weight_kg
It is just a single string requiring no escaping, and makes it clear what the units are. A better option might be to just use supp_weight, and maybe just keep a note somewhere that the column uses kilograms as the unit by default.

You will need to use quoted identifiers but I strongly recommend not to do that:
create table supp_details
(
supp_id integer,
supp_name text,
"supp_weight(kg)" integer
);

Adding bracket symbols into your column names is possible but probably a bad idea. If you want to micromanage the name just for display purposes of the end result, you should probably do it in an alias, using the AS keyword.
SELECT supp_id, supp_name, supp_weight AS "supp_weight(Kg)" FROM ...
Or add the decorations on the client side before it displays the results.

Related

Replace single quote to regular abbreviation

I have a table with a state column. Inside the state column I have a value like TX` I want to replace that ending character to make the State read TX. How would I do that please give examples
You already have answers for replacing the quote, but I wanted to provide methods for avoiding this problem in the first place.
As noted in #SeanLange's answer, you can use define your State field as a CHAR(2) , so you know that you'll never have a dummy character following a valid state code. You could also handle this in your client code, sanitizing the input before even sending to the database.
One could argue that it would even be a good idea to define a lookup table with a foreign key constraint, so users could only input valid values. You could also use this lookup table client-side (e.g. to provide a list of states).
Of course, you also have to consider internationalization: What about when/if you need to store locations outside of the United States, that may have > 2 characters?
You can escape a single quote by doubling it and including it in quotes. So:
select replace(state, '''', ''')
Of course, if the problem is just a bad third character, then LEFT(state, 2) might do the trick as well.
As a Sean Lang's comment said, you can do this in many different ways. For simplicity, you can just use LEFT(string, #) function for the whole typecasting as long as your raw values are all in the TX` format (**two letter abbrev and one ` , so three characters total for every value in that field.
If that is the case then just do:
SELECT CAST(LEFT(t.state_column, 2) As Varchar(2)) As state,
t.column_2,
t.column_3
/* and so on for all the columns you want */
FROM table t;
--
Further Reference:
- https://w3resource.com/PostgreSQL/left-function.php

invalid identifier for creating table

create table ROOM
(NO_ROOM INT PRIMARY KEY, TYPE VARCHAR2(8) NOT NULL, SIZE VARCHAR2(8) NOT NULL)
;
I get ORA-00904, i think problem is from NO_ROOM. I try to use NUMBER, it's same.
PS. I make table for room that has no.room type and size.
SIZE is a reserved keyword. That means we cannot use it as an identifier (unless we put it in double quotes, but double-quoted identifiers are Teh Suck! so don't do that). Change the column name to ROOMSIZE and your statement will run.
Note that TYPE is also a keyword but not reserved. So we are allowed to use it as a column identifier. Types weren't introduced until 8; making TYPE a reserved keyword would have broken code in Oracle applications all over the world, not least in its own data dictionary.
The documentation has a complete list of the reserved words. Find it here.
Why would using "SIZE" be such a bad idea? After all, as #JavaBeginner says, the SQL standard does permit it.
Once we choose to use double-quotes to get around Oracle's naming rules we are condemned to use them whenever we reference the column. Hence this would not be a valid query:
select no_room, size
from room
where size > 10
We would have to write instead:
select no_room, "SIZE"
from room
where "SIZE" > 10
And it always have to be "SIZE": "size" is a different identifier. so is "Size".
Best practice is the informed interpretation of what the standards permit. SQL allows us to do things which we shouldn't do if we want to build a robust and maintainable database. Not using double-quoted identifiers falls into that category.
Size is a keyword and it cannot be used as column name unless you use it with double quotes. My suggestion is to use some other name for column as room_size. If you still want to use SIZE as column name for some reason, you will need to use double quotes while creating the table and also take care of the same while doing any other queries using this column.
Here is the working fiddle with size used as column name http://sqlfiddle.com/#!4/7e746
I do want to add(same as above) that using reserved word for column name(using double quotes) is a bad idea.
You can't use any of these reserved words as identifiers:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/ap_keywd.htm
Size is in the list. If you choose another name for the column you should be okay.
SIZE is a reserved word by Oracle! So, it's not allowed to use them as a name of variables or objects. You can find here http://docs.oracle.com/cd/B28359_01/appdev.111/b31231/appb.htm list of reserved words for Oracle 11g.
Here is the second moment, you can use it inside double quote like "SIZE" or "Size", but that will be case sensitive and not recommended.

Table or column name cannot start with numeric?

I tried to create table named 15909434_user with syntax like below:
CREATE TABLE 15909434_user ( ... )
It would produced error of course. Then, after I tried to have a bit research with google, I found a good article here that describe:
When you create an object in PostgreSQL, you give that object a name. Every table has a name, every column has a name, and so on. PostgreSQL uses a single data type to define all object names: the name type.
A value of type name is a string of 63 or fewer characters. A name must start with a letter or an underscore; the rest of the string can contain letters, digits, and underscores.
...
If you find that you need to create an object that does not meet these rules, you can enclose the name in double quotes. Wrapping a name in quotes creates a quoted identifier. For example, you could create a table whose name is "3.14159"—the double quotes are required, but are not actually a part of the name (that is, they are not stored and do not count against the 63-character limit). ...
Okay, now I know how to solve this by use this syntax (putting double quote on table name):
CREATE TABLE "15909434_user" ( ... )
You can create table or column name such as "15909434_user" and also user_15909434, but cannot create table or column name begin with numeric without use of double quotes.
So then, I am curious about the reason behind that (except it is a convention). Why this convention applied? Is it to avoid something like syntax limitation or other reason?
Thanks in advance for your attention!
It comes from the original sql standards, which through several layers of indirection eventually get to an identifier start block, which is one of several things, but primarily it is "a simple latin letter". There are other things too that can be used, but if you want to see all the details, go to http://en.wikipedia.org/wiki/SQL-92 and follow the links to the actual standard ( page 85 )
Having non numeric identifier introducers makes writing a parser to decode sql for execution easier and quicker, but a quoted form is fine too.
Edit: Why is it easier for the parser?
The problem for a parser is more in the SELECT-list clause than the FROM clause. The select-list is the list of expressions that are selected from the tables, and this is very flexible, allowing simple column names and numeric expressions. Consider the following:
SELECT 2e2 + 3.4 FROM ...
If table names, and column names could start with numerics, is 2e2 a column name or a valid number (e format is typically permitted in numeric literals) and is 3.4 the table "3" and column "4" or is it the numeric value 3.4 ?
Having the rule that identifiers start with simple latin letters (and some other specific things) means that a parser that sees 2e2 can quickly discern this will be a numeric expression, same deal with 3.4
While it would be possible to devise a scheme to allow numeric leading characters, this might lead to even more obscure rules (opinion), so this rule is a nice solution. If you allowed digits first, then it would always need quoting, which is arguably not as 'clean'.
Disclaimer, I've simplified the above slightly, ignoring corelation names to keep it short. I'm not totally familiar with postgres, but have double checked the above answer against Oracle RDB documentation and sql spec
I'd imagine it's to do with the grammar.
SELECT 24*DAY_NUMBER as X from MY_TABLE
is fine, but ambiguous if 24 was allowed as a column name.
Adding quotes means you're explicitly referring to an identifier not a constant. So in order to use it, you'd always have to escape it anyway.

Add fraction constraint to a column in oracle

I am using oracle 10gr2. I am trying to enforce a constraint on a column called "score" such that only fractions can be entered.
More specifically, a the format should contain one digit in the numerator and one digit in the denominator, such that a user can only enter a fraction such as 3/4,2/5,or 7/8. The column only accepts numbers as the input. Can anyone show me the SQL to use?
If I understand correctly, I think the proper way to do this is to store the data in two columns. This especially makes sense if the top number is a user's actual score on a problem and the bottom number is the possible score, which is what it sounds like you are doing. This will enable you to sum up scores using the built in number functions in Oracle rather than parsing strings. Then, you limit the size of each column to (0-9) by using the type NUMBER(1,0). For example:
alter table table_name add (
column possible number(1,0),
column actual number(1,0)
);
If you have data in the score column already, you then copy your values over from there to your new columns. Finally, you drop that column.
alter table table_name drop score;
Also, I'd do a search on "Oracle less than constraint", because you probably don't want the actual score to exceed the possible, and probably do a similar constraint to make the possible score greater than zero.
I don't have an instance of Oracle to test against, but here are some pointers and some untested code:
Pointers:
Look here on how to create a check constraint: http://www.techonthenet.com/oracle/check.php
After you know that, you can use Regex to validate the input. Read here for further reference: http://psoug.org/reference/regexp.html
You are probably going to use REGEX_LIKE and it would look like something like this:
ALTER TABLE your_table
add CONSTRAINT check_your_field
CHECK (REGEXP_LIKE(your_field, '^[0-9]+/[0-9]+$'));
Warning: this is not guaranteed to be fully functional code. It's a lead. Read, research and adjust accordingly.
A caveat: 1/0 will be considered valid by the Regex above, but we all know it should not be. There's a way you can know about the second part of the fraction. Read the Regex link, everything you need to know is there.
The domain of valid values is finite and small. Therefore, consider putting them all in a table, using a fixed width text column (i.e. three characters) and a create a foreign reference to this lookup table, rather than a CHECK constraint.

Force numerical order on a SQL Server 2005 varchar column, containing letters and numbers?

I have a column containing the strings 'Operator (1)' and so on until 'Operator (600)' so far.
I want to get them numerically ordered and I've come up with
select colname from table order by
cast(replace(replace(colname,'Operator (',''),')','') as int)
which is very very ugly.
Better suggestions?
It's that, InStr()/SubString(), changing Operator(1) to Operator(001), storing the n in Operator(n) separately, or creating a computed column that hides the ugly string manipulation. What you have seems fine.
If you really have to leave the data in the format you have - and adding a numeric sort order column is the better solution - then consider wrapping the text manipulation up in a user defined function.
select colname from table order by dbo.udfSortOperator(colname)
It's less ugly and gives you some abstraction. There's an additional overhead of the function call but on a table containing low thousands of rows in a not-too-heavily hit database server it's not a major concern. Make notes in the function to optomise later as required.
My answer would be to change the problem. I would add an operatorNumber field to the table if that is possible. Change the update/insert routines to extract the number and store it. That way the string conversion hit is only once per record.
The ordering logic would require the string conversion every time the query is run.
Well, first define the meaning of that column. Is operator a name so you can justify using chars? Or is it a number?
If the field is a name then you will use chars, and then you would want to determine the fixed length. Pad all operator names with zeros on the left. Define naming rules for operators (I.E. No leters. Or the codes you would use in a series like "A001")
An index will sort the physical data in the server. And a properly define text naming will sort them on a query. You would want both.
If the operator is a number, then you got the data type for that column wrong and needs to be changed.
Indexed computed column
If you find yourself ordering on or otherwise querying operator column often, consider creating a computed column for its numeric value and adding an index for it. This will give you a computed/persistent column (which sounds like oxymoron, but isn't).