How to have two attributes, together, be unique? - database

I have a user class which looks like this:
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(15), unique=True, nullable=False)
last_name = db.Column(db.String(15), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(60), nullable=False)
def __repr__(self):
return f"User('{self.first_name}', '{self.last_name}', '{self.email}')"
As you can see, first_name and last_name have to be unique, but that's not really what I want. Instead, I'd like the full name to be unique, so first_name and last_name together has to be unique. How can I do that?

You can use a Declarative Table Configuration and define a UNIQUE constraint. However, keep in mind that there can be several people with the same first and last name combination.
class User(db.Model, UserMixin):
__table_args__ = (db.UniqueConstraint('first_name', 'last_name'),)
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(15), nullable=False)
last_name = db.Column(db.String(15), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(60), nullable=False)
def __repr__(self):
return f"User('{self.first_name}', '{self.last_name}', '{self.email}')"

Related

ASP.Net MVC - Insert and Update

I'm trying to insert and update into my database but I don't know how to use SQL in this context. Was following iamtimcorey on YouTube: https://www.youtube.com/watch?v=bIiEv__QNxw&t=2322s
Business Logic (EmloyeeProcessor)
public static int CreateEmployee(string Employee_number, string First_name, string Last_name,
string Email, string Research_Area, string Position_held,
string Highest_qualification, string Department_name)
{
Employee_Model data = new Employee_Model
{
Employee_number = Employee_number,
First_name = First_name,
Last_name= Last_name,
Email = Email,
Research_area = Research_Area,
Position_held = Position_held,
Highest_qualification = Highest_qualification,
Department_name = Department_name,
};
string sql = #"DECLARE #var_Department_id int;
SELECT #var_Department_id = Department_id
FROM dbo.Departments
WHERE dbo.Departments.Department_name = #Department_name;
INSERT INTO dbo.Employee (Employee_number, First_name, Last_name, Email, Research_area, Position_held, Highest_qualification, #var_Department_id)
VALUES (#Employee_number, #First_name, #Last_name, #Email, #Research_area, #Position_held, #Highest_qualification, #Department_name);";
return SqlDataAccess.SaveData(sql, data);
}
Department_name = Department_name returns a string that's already present in the Department's Table. Department name is a string in table Departments. I want to pass in the matching Department_id from that table into the New Employee I'm creating.
public static class SqlDataAccess
{
public static string GetConnectionString(string connectionName = "DemoDB")
{
return ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
}
public static List<T> LoadData<T>(string sql)
{
using (IDbConnection cnn = new SqlConnection(GetConnectionString()))
{
return cnn.Query<T>(sql).ToList();
}
}
}
I think the SQL-query should look like this:
DECLARE #var_Department_id int;
SELECT #var_Department_id = Department_id
FROM dbo.Departments
WHERE dbo.Departments.Department_name = #Department_name;
/*
Final insert into table dbo.Employee.
*/
INSERT INTO dbo.Employee (
Employee_number,
First_name,
Last_name,
Email,
Research_area,
Position_held,
Highest_qualification,
Department_id --This was #var_Department_id in your query
)
VALUES (
#Employee_number,
#First_name,
#Last_name,
#Email,
#Research_area,
#Position_held,
#Highest_qualification,
#var_Department_id --This was #Department_name in your query
);";

How can I delete registries from different tables without using schema in Elixir

I am trying to delete a register from some tables, all related to same user Id since Elixir, but using an external SQL Server database. I want to delete the tables in a specific order but without using Schema. I want to execute these SQL queries
SELECT *
FROM UsersConfig
WHERE UserId = 'D9960E26-3F7F-4F8C-954A-FF6316D7A3B3'
SELECT *
FROM UserBranch
WHERE UserId = 'D9960E26-3F7F-4F8C-954A-FF6316D7A3B3'
DECLARE #userCompanyPreferencesId uniqueidentifier
SELECT #userCompanyPreferencesId = UserCompanyPreferencesId
FROM UserCompany
WHERE UserId = 'D9960E26-3F7F-4F8C-954A-FF6316D7A3B3'
SELECT *
FROM UserCompany
WHERE UserId = 'D9960E26-3F7F-4F8C-954A-FF6316D7A3B3'
SELECT *
FROM UserCompanyPreferences
WHERE UserCompanyPreferencesId = #userCompanyPreferencesId
SELECT *
FROM Users
WHERE UserId = 'D9960E26-3F7F-4F8C-954A-FF6316D7A3B3'
But I dont want to add unused schemas to elixir protect. I am trying to do something like this:
def delete_user_by_user_number(user_id) do
query = """
DELETE UsersConfig WHERE UserId = $1
DELETE UserBranch WHERE UserId = $1
DECLARE #userCompanyPreferencesId uniqueidentifier
SELECT #userCompanyPreferencesId = UserCompanyPreferencesId FROM UserCompany WHERE UserId = $1
DELETE UserCompany WHERE UserId = $1
DELETE UserCompanyPreferences WHERE UserCompanyPreferencesId = #userCompanyPreferencesId
DELETE Users WHERE UserId = $1
"""
Ecto.Adapters.SQL.stream(UsersRepo, query, [user_id])
end
But only I get the query translated to SQL
%Ecto.Adapters.SQL.Stream{
meta: %{
cache: #Reference<0.3298680420.2890006536.27915>,
opts: [timeout: 15000, pool_size: 2, pool:
m DBConnection.ConnectionPool],
pid: #PID<0.749.0>,
repo: ChainUtils.UsersRepo,
sql: Ecto.Adapters.Tds.Connection,
telemetry: {ChainUtils.UsersRepo, :debug,
[:chain_utils, :users_repo, :query]
}
},
opts: [],
params: ["D9960E26-3F7F-4F8C-954A-FF6316D7A3B3"],
statement: "DELETE UsersConfig WHERE UserId = $1\nDELETE UserBranch WHERE UserId = $1\nDECLARE #userCompanyPreferencesId uniqueidentifier
\nSELECT #userCompanyPreferencesId = UserCompanyPreferencesId FROM UserCompany WHERE UserId = $1\nDELETE UserCompany WHERE UserId = $1\nDELETE UserCompanyPreferences WHERE UserCompanyPreferencesId = #userCompanyPreferencesId\nDELETE Users WHERE UserId = $1\n"
}
Can you help me with some ideas to do something like this?
The reason nothing is happening is because you're using Ecto.Adapters.SQL.stream. This function creates a lazy stream of results from your query and nothing will actually happen until you start consuming that stream. I wouldn't use it for a query that is only needed for its side-effects, like a delete - use Ecto.Adapters.SQL.query! instead. Maybe something like:
queries = [
"DELETE UsersConfig WHERE UserId = $1",
"DELETE UserBranch WHERE UserId = $1",
"DECLARE #userCompanyPreferencesId uniqueidentifier",
"SELECT #userCompanyPreferencesId = UserCompanyPreferencesId FROM UserCompany WHERE UserId = $1",
"DELETE UserCompany WHERE UserId = $1",
"DELETE UserCompanyPreferences WHERE UserCompanyPreferencesId = #userCompanyPreferencesId",
"DELETE Users WHERE UserId = $1"
]
for query <- queries do
Ecto.Adapters.SQL.query!(UsersRepo, query, [user_id])
end

Escape keywords from #where clause in Entity for Hibernate

I have an Entity class as below.
#Entity
#Table(name = "user_MAIN" )
public class userDetails implements Serializable {
#Id
#Column(name = "user_ID")
private int userId;
#OneToMany
#JoinColumn(name = "user_ID", insertable = false, updatable = false)
#Where(clause = "CAST(START_DATE AS DATE) <= CAST(getDate() AS DATE)")
private Set<userContractBasic> userContract=new HashSet<userContractBasic>();
}
I want to join this with userContractBasic entity with a where condition START_DATE > current_date. Here I want only date check required, not date-time check. So I've added CAST in #where clause.
But after adding CAST the query while fetching all results are :
SELECT <fields>
FROM user_main um
LEFT OUTER JOIN user_contract uc ON um.user_id=uc.user_id
AND CAST(uc.START_DATE AS uc.DATE) <= CAST(getDate() AS uc.DATE)
The DATE keyword in ON clause is prepended with the table alias and its breaking the query.
Is there any way I can avoid it?
you need not to specify AS keyword there
just change your #Where with following
#Where(clause = "CAST(START_DATE) <= CAST(getDate())")

Using MyBatis to Insert into Sybase table with IDENTITY column as ID. How do I get ID returned?

I need to get the auto generated ID when doing the insert below. The insertRecord method returns the number of rows written. That is fine and expected. The Object Log, however, does not have it's id field updated to the auto generated ID. Any ideas?
CREATE TABLE LOG
(
ID NUMERIC(20,0) IDENTITY,
NAME VARCHAR(20) NOT NULL,
DESCRIPTION VARCHAR(200) NOT NULL,
USR VARCHAR(20) NOT NULL
)
public class Log
{
private long id;
private String name;
private String description;
private String user;
//getters+setters......
}
int insertRecord(#Param("log") Log log);
<insert id="insertRecord" parameterType="com.xxx.yyy.zzz.model.Log" useGeneratedKeys="true" keyProperty="id">
INSERT INTO LOG (NAME, DESCRIPTION, USR)
VALUES (#{log.name}, #{log.description}, #{log.user})
<selectKey keyProperty="id" resultType="long">
select ##identity
</selectKey>
</insert>
Got it.
The keyProperty in the select needed to be log.id. See below.
<selectKey keyProperty="log.id" resultType="long">
select ##identity AS id
</selectKey>

Using a concatenated value of two columns to display data

I'm trying to use a concatenated value of two columns to display data. I'm first testing out ways to do this in a query before actually using it in a stored proc but I just don't get any results back.
So I have a table called Person:
CREATE TABLE Person
(
IDNumber char(13) NOT NULL,
Name varchar(MAX) NOT NULL,
Surname varchar(MAX) NOT NULL,
Age int NOT NULL,
PRIMARY KEY (IDNumber)
)
I want to display all the data available if the concatenated value of Name and Surname is equal to say 'Harriet West' but I'm not sure how to do this. Can anyone help by explaining how to do this?
You want a computed column such as:
CREATE TABLE Person (
IDNumber char(13) NOT NULL,
Name varchar(MAX) NOT NULL,
Surname varchar(MAX) NOT NULL,
Age int NOT NULL,
Fullname AS Name + ' ' + Surname,
PRIMARY KEY (IDNumber)
)
Example
INSERT INTO Person (IDNumber, Name, Surname, Age)
VALUES ('1', 'Bob', 'Smith', 10);
You can then query the computed column:
SELECT [column list] FROM Person WHERE Fullname = 'Bob Smith';
Result
| IDNUMBER | NAME | SURNAME | AGE | FULLNAME |
|---------------|------|---------|-----|-----------|
| 1 | Bob | Smith | 10 | Bob Smith |
Documentation
Some other thoughts:
It seems silly to give IDNumber a string data type; perhaps call it something else?
Do you really need varchar(max) for name columns?
Don't store a calculated value. You should store the date of birth of the person, then calculate the age.
I like the computed column approach, but if you don't want it, in your query you can do:
SELECT IDNumber, Name, Surname, Name + ' ' + Surname [Full Name], Age
FROM Person
If you want to query by the Full Name you could do:
SELECT IDNumber, Name, Surname, Age
FROM Person
WHERE Name + ' ' + Surname = 'Harriet West'
sqlfiddle demo
In the where clause...
Select * from Person
Where SurName + ' ' + Name = 'Harriet West'
Be sure to set concat_null_yields_null Off if there is a chance that SurName or Name could be Null.

Resources