Customized ID in PostgreSQL using the user's input - postgresql

I need to create an ID that uses data from the user's input. For example, the first letter is "M" the second is the year of birth that the user inputs, then the two first characters of the province the user lives in (for example, ON for Ontario), and then a sequence of random numbers. Like this: M-1990-ON-0001
Do you have any idea how I can do that?

You can do that as a generated column. ie:
customId text GENERATED ALWAYS AS ('M-'||extract(year from birthdate)::char(4)||'-'||province) STORED
However, you should never make such info a primary key. Just use a key for yourself but do not as a primary key.
DBFiddle demo
If you think about it such a value wouldn't be even unique (same province, same year, two persons for example).

Related

FileMaker - Getting Data From Another Table with Multiple Field Restrictions

I can't think of a better title, so feel free to make a suggestion once you understand the issue.
I was given a table to work with that I need to call from another table:
Name
Month
Type
Value
For each record in the main table I need to pull one "Value" that corresponds to it. What it is will be determined by all three of the other fields. So for example, if a record in the main table is:
Name:
Google
Date:
3\17\2016
Type:
M
Then I need to pull the value for the record in the other table where the Name is "Google", the month is "3", and the type is "M".
I was able to do this successfully (if slowly) using an ExecuteSQL command in a calculation field, with a ton of nested If statements for the names (I have yet to figure out how to input the record's data directly into the ExecuteSQL statement, it breaks when I try). I would prefer to just grab the data directly. I can't switch over to the other layout because I need to see all of the records at once. I can't do a simple relationship because there isn't a real relationship, it's like there are three foreign keys working in tandem and I only know how to use one to call the data.
Any idea on how to do this more simplistically?
Some ideas I've had but not sure if it will work:
Using a calculation field as a related field to dynamically point to the row by code (concatenate the three relevant fields into a type of code). Not sure if you can connect two tables by a calculation field.
Doing that same thing when calling the data into the table in the first place, adding a code to create a single primary key.
Here are my relationships:
I can't do a simple relationship because there isn't a real
relationship, it's like there are three foreign keys working in tandem
and I only know how to use one to call the data.
Simply define a relationship with three predicates - i.e. three pairs of match fields.

Data type for storing long lists

What is the correct way of storing large lists in PostgreSQL?
I currently have a "user" table, where the "followers" column stores a list of the followers that that user has. This list is stored in JSON, and every time the server wants to add a new user to that list, it retrieves it from the database, appends the new user, and then replaces the old list with the new list.
The problem is that these lists tend to get quite lengthy, which might affect performance. Is it possible to simply append to the list directly via SQL without retrieving it and rewriting it later?
Use a separate table for followers. The table should have at least two columns: userid and followerid. And it's good practice to have a primary key for this table as well, so let's give it a "ufid".
You can do a select to get all the elements and compute the JSON string if your application needs it. But do not work with JSON or any other string representation of the list, as it defeats the purpose of a relational database.
To add a new follower, simply add a new record to the follower table with the userid; deleting and update are also done on the record level without working with the "other records".
If followers is a list of integers which are primary keys to their accounts, make it an integer array int[]. If they are usernames or other words, go with a string array character varying[].
To append to an array column you can do this:
UPDATE the_table SET followers = followers || new_follower WHERE id = user;

Generating a customer ID in a form

I have a customer table 'tblCustomer' that contains a primary key column called CustID. CustID refers to the Customer as their own ID number.
Now, I am in the process of creating a form that will allow people to add new customers. To do that, I need to generate a new CustID. My CustID starts at '10000' and go up by 1 each time. It is important to note that this field is a text field, not a number field.
There must be an ID, otherwise the record cannot be created as the primary key field is a mandatory field and is also tied to other relationships in the database.
As such, I am creating a button next to the ID field on the form that will generate an ID in the textbox. It needs to start at whatever the custID's highest key value is and increment it by 1. The problem is that it is a text field and cannot change.
I am unsure how to do this, personally. I have tackled it quite a few ways but all lead me back to the same spot - I don't know how to do this with custID being a text value rather than a numerical value. I have been thinking of doing a conversion of some sort as the calculation occurs but I have no idea how to do this at all.
I'm a bit of a newbie with Access, so any help would be appreciated!
Assuming that all CustID's are numbers, you can do the following to get a new ID:
Dim strMax As String
Dim intMax As Integer
strMax = DMax("CustID", "<your table name>")
intMax = CInt(strMax) + 1
strMax will hold the current maximum id, and intMax will hold the new ID. If strMax contains a non numeric value however this code will fail - you would need an error handler to work around it.
Just need to put it in the buttons click event.
Hope this helps!
Simon

What are the proper use-cases for the PostgreSQL Array Datatype?

It seems to me that the functionality of the PostgreSQL array datatype overlaps a lot with the standard one-to-many and many-to-many relationships.
For example, a table called users could have an array field called "favorite_colors", or there could be a separate table called "favorite_colors" and a join table between "users" and "favorite_colors".
In what cases is the array datatype OK to use instead of a full-blown join?
An array should not be used similar to a relation. It should rather contain indexed values that relate to one row very tightly. For example if you had a table with the results of a football match, than you would not need to do
id team1 team2 goals1 goals2
but would do
id team[2] goals[2]
Because in this example, most would also consider normalizing this into two tables would be silly.
So all in all I would use it in cases where you are not interested in making relations and where you else would add fields like field1 field2 field3.
One incredibly handy use case is tagging:
CREATE TABLE posts (
title TEXT,
tags TEXT[]
);
-- Select all posts with tag 'kitty'
SELECT * FROM posts WHERE tags #> '{kitty}';
I totally agree with #marc. Arrays are to be used when you are absolutely sure you don't need to create any relationship between the items in the array with any other table. It should be used for a tightly coupled one to many relationship.
A typical example is creating a multichoice questions system. Since other questions don't need to be aware of the options of a question, the options can be stored in an array.
e.g
CREATE TABLE Question (
id integer PRIMARY KEY,
question TEXT,
options VARCHAR(255)[],
answer VARCHAR(255)
)
This is much better than creating a question_options table and getting the options with a join.
The Postgresql documentation gives good examples:
CREATE TABLE sal_emp (
name text,
pay_by_quarter integer[],
schedule text[][]
);
The above command will create a table named sal_emp with a column of
type text (name), a one-dimensional array of type integer
(pay_by_quarter), which represents the employee's salary by quarter,
and a two-dimensional array of text (schedule), which represents the
employee's weekly schedule.
Or, if you prefer:
CREATE TABLE tictactoe (
squares integer[3][3] );
If I want to store some similar type of set of data, and those data don't have any other attribute.
I prefer to use arrays.
One example is :
Storing contact numbers for a user
So, when we want to store contact number, usually main one and a alternate one, in such case
I prefer to use array.
CREATE TABLE students (
name text,
contacts varchar ARRAY -- or varchar[]
);
But if these data have additional attributes, say storing cards.
A card can have expiry date and other details.
Also, storing tags as an array a bad idea. A tag can be associated to multiple posts.
Don't use arrays in such cases.

DB2 - handling columns defined as null

Let's say you have three textboxes that you can use to search for data. Each textbox will correspond to a column on the DB2 table. The search string you enter will be inserted into the where clause. For example, you have First-Name, Last-Name, and Phone Number. If you don't enter data into a particular textbox, I default its value in the where clause to '_', the wildcard character to select everything. Also, lets say Phone Number is defined as NULL on the table.
Cursor1 will be used if the user has entered a Phone number to search for. So the where clause will look something like this:
Where FIRST_NAME like :firstname AND
LAST_NAME like :lastname AND
PHONE_NBR like :number
This works when data is entered for phone number. But if a search is done for First Name only, the cursor returns partial or no results because the :number host variable will be populated with the "_' wildcard. PHONE_NBR like '_' will only return the rows that have a real value. If there is a null for PHONE_NBR on a row that matches the First Name you searched for, that row won't show up. So I created a second cursor.
Cursor2 will be used if the user HAS NOT entered a Phone number to search for. The Where clause looks something like this.
Where FIRST_NAME like :firstname AND
LAST_NAME like :lastname AND
(PHONE_NBR like :number OR
PHONE_NBR IS NULL)
So again, if a search was done for a first name only, and some values in PHONE_NBR have data, some are null, EVERYTHING that matches the first name that is searched for will show in the results - which is good. For the rows with values in PHONE_NBR, PHONE_NBR like '_' will get those. For the rows with null in PHONE_NBR, PHONE_NBR IS NULL will get those.
This is a minor yet necessary difference. Because of this minor difference, I would like to combine these two cursors into one. How can that be done to achieve the same results?
Ian, i think the difference is if the user supplies a number he doesn't want to return rows with a null. using cursor 2 all the time would return rows with null along with matching numbers.
You could try a CASE statement based on :number...though i'm not sure if you can use a CASE with "is null" syntax. i know you could if you were just checking for different values (equal to, less than, etc).
The way I'd recommend handling this is by building the query to supply conditions only on the columns where the user enters data. That is:
If the user enters something in the First_Name text box, you have a condition such as:
FIRST_NAME LIKE '...'
If the user enters something in the Last_Name text box, you have a condition such as:
LAST_NAME LIKE '...'
If the user enters something in the Phone_Nbr text box, you have a condition such as:
PHONE_NBR LIKE '...'
In each case, the 3 dots represent a string derived from the information typed into the text box, and the function that does that conversion is fully aware of quoting (to avoid SQL injection).
If the user types in two or three of the text boxes, the independent conditions are joined by an AND. If the user types nothing, you can generate a tautology such as 1 = 1 as the condition.
You then append that condition to the WHERE clause of the SQL statement, and then arrange to execute it.
This is the technique made available by the CONSTRUCT statement in IBM Informix 4GL; it has been available there since 1986. It allows for conditions other than just LIKE, such as equals, less than, greater than or equal to, ranges, or even a list of alternatives (for an IN ('val1', 'val2', ...) condition), and it can be used for all data types.