1st table
CREATE TABLE qualified (
facultyid integer NOT NULL,
courseid character varying(16) NOT NULL,
datequalified character varying(16),
dq2 date,
CONSTRAINT qualified_pkey PRIMARY KEY (facultyid, courseid)
);
INSERT INTO qualified VALUES (3467, 'ISM 4212', to_date('9/1995', 'MM/YYYY'), date '1995-09-01');
INSERT INTO qualified VALUES (4756, 'ISM 3112', to_date('9/1991', 'MM/YYYY'), date '1991-09-01');
INSERT INTO qualified VALUES (2143, 'ISM 3113', to_date('9/1988', 'MM/YYYY'), date '1988-09-01');
INSERT INTO qualified VALUES (4756, 'ISM 3113', to_date('9/1991', 'MM/YYYY'), date '1991-09-01');
INSERT INTO qualified VALUES (2143, 'ISM 3112', to_date('9/1988', 'MM/YYYY'), date '1988-09-01');
INSERT INTO qualified VALUES (3467, 'ISM 4930', to_date('9/1996', 'MM/YYYY'), date '1996-09-01');
2nd table:
CREATE TABLE faculty (
facultyid integer NOT NULL,
facultyname character varying(25),
CONSTRAINT faculty_pkey PRIMARY KEY (facultyid)
);
INSERT INTO faculty VALUES (2143, 'Birkin');
INSERT INTO faculty VALUES (3467, 'Berndt');
INSERT INTO faculty VALUES (4756, 'Collins');
The following query with the minus operator displayed the correct result:
SELECT q.facultyid, facultyname
FROM qualified q, faculty fa
WHERE q.facultyid = fa.facultyid AND courseid = 'ISM 3113'
MINUS
SELECT q.facultyid, facultyname
FROM qualified q, faculty fa
WHERE q.facultyid = fa.facultyid AND courseid = 'ISM 4930';
The following WHERE NOT EXISTS displays the incorrect result
SELECT q.facultyid, facultyname
FROM qualified q, faculty fa
WHERE q.facultyid = fa.facultyid AND courseid = 'ISM 3113'
AND NOT EXISTS (SELECT q.facultyid, facultyname
FROM qualified q, faculty fa
WHERE q.facultyid = fa.facultyid AND courseid = 'ISM 4930');
The following worked.
The 2nd WHERE clause must feature an ALIAS referring to the table listed in the first FROM clause that possess all the columns to be listed in the first SELECT clause.
SELECT q.facultyid, facultyname
FROM qualified q, faculty fa
WHERE q.facultyid = fa.facultyid AND courseid = 'ISM 3113'
AND NOT EXISTS (SELECT q.facultyid, facultyname
FROM qualified q2, faculty fa2
WHERE q2.facultyid = fa.facultyid AND courseid = 'ISM 4930');
Better query:
SELECT fa.facultyid, facultyname
FROM qualified q, faculty fa
WHERE q.facultyid = fa.facultyid AND courseid = 'ISM 3113'
AND NOT EXISTS (SELECT facultyid
FROM qualified
WHERE facultyid = fa.facultyid AND courseid = 'ISM 4930');
Thanks to 'Joel Murach MySQL' text book for having a similar question.
Related
This is a simply question.
I have been playing with SQLAlchemy and I'm now at the point of dealing with Unique Constraints in a Table.
So, when a Unique Constraint is violated, an IntegrityError exception is raised. If I have multiple Unique Constraints defined for a Table, how can I distinguish between them through the raised exception?
EDIT:
I'm using sqlite3 underneath.
FINAL EDIT:
AVC answer provides an alternative solution, by checking in the message error for the columns that violated the constraint. It's not an elegant solution but it gets the job done.
The integrity error will tell you which column has violated the constraint. For example:
IntegrityError: (IntegrityError) insert or update on table "my_table"
violates foreign key constraint "my_table_some_column_fkey"
In your case you are declaring your constraint like this:
UniqueConstraint('datapath_port_id', 'datapath_id',
'controller_id', name='unique_registration')
What you are doing here is not declaring multiple uniqueness constrains. That would look something like this:
Column('datapath_port_id', unique=True)
Column('datapath_id', unique=True)
Column('controller_id', unique=True)
Instead you have created a multicolumn or composite uniqueness constraint which means that the combination of all three columns must be unique.
So if you had a database row A, B, C with your multicolumn uniqueness constraint you could still insert A, A, A even though there is already the value A in the first row. Similarly, B, B, B and C, C, C would also be valid inserts. What would fail though is trying to insert A, B, C again. That fails because all the columns match an existing row, which is why the uniqueness error you're seeing lists all the columns.
Here is an example with code:
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer
from sqlalchemy import UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
engine = create_engine('sqlite:///:memory:', echo=True)
Base = declarative_base()
class Test(Base):
__tablename__ = 'test'
__table_args__ = (
UniqueConstraint('a', 'b', name='ab_constraint'),
UniqueConstraint('b', 'c', name='bc_constraint'))
id = Column(Integer, primary_key=True)
a = Column(Integer)
b = Column(Integer)
c = Column(Integer)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
session.add(Test(a=1, b=1, c=1))
session.add(Test(a=2, b=2, c=2))
From there we can try to violate the different uniqueness constraints to see what happens. If try to run this command:
session.add(Test(a=1, b=1, c=2))
session.commit()
We get:
sqlalchemy.exc.IntegrityError: (IntegrityError) UNIQUE constraint failed: test.a, test.b u'INSERT INTO test (a, b, c) VALUES (?, ?, ?)' (1, 1, 2)
And then if we try to violate the second constraint:
session.add(Test(a=1, b=2, c=2))
session.commit()
We instead get:
sqlalchemy.exc.IntegrityError: (IntegrityError) UNIQUE constraint failed: test.b, test.c u'INSERT INTO test (a, b, c) VALUES (?, ?, ?)' (1, 2, 2)
With the first case specifying that test.a and test.b violated the constraint and the second one specifying test.b and test.c.
The names I chose for those constraints (ab_constraint and bc_constraint) are however are not included in the response. They are however present in at the database level. We can see this by echoing the database creation commands:
CREATE TABLE test (
id INTEGER NOT NULL,
a INTEGER,
b INTEGER,
c INTEGER,
PRIMARY KEY (id),
CONSTRAINT ab_constraint UNIQUE (a, b),
CONSTRAINT bc_constraint UNIQUE (b, c)
)
However, even at the database level (I'm using SQLite) the constraint name is not used in the error message:
sqlite> INSERT INTO test (a, b, c) VALUES (1, 1, 1);
sqlite> INSERT INTO test (a, b, c) VALUES (2, 2, 2);
sqlite> INSERT INTO test (a, b, c) VALUES (1, 1, 2);
Error: UNIQUE constraint failed: test.a, test.b
Here's the issue. I have 2 tables that I am currently using in a pivot to return a single value, MAX(Date). I have been asked to return additional values associated with that particular MAX(Date). I know I can do this with an OVER PARTITION but it would require me doing about 8 or 9 LEFT JOINS to get the desired output. I was hoping there is a way to get my existing PIVOT to return these values. More specifically, let's say each MAX(Date) has a data source and we want that particular source to become part of the output. Here is a simple sample of what I am talking about:
Create table #Email
(
pk_id int not null identity primary key,
email_address varchar(50),
optin_flag bit default(0),
unsub_flag bit default(0)
)
Create table #History
(
pk_id int not null identity primary key,
email_id int not null,
Status_Cd char(2),
Status_Ds varchar(20),
Source_Cd char(3),
Source_Desc varchar(20),
Source_Dttm datetime
)
Insert into #Email
Values
('test#test.com',1,0),
('blank#blank.com',1,1)
Insert into #History
values
(1,'OP','OPT-IN','WB','WEB','1/2/2015 09:32:00'),
(1,'OP','OPT-IN','WB','WEB','1/3/2015 10:15:00'),
(1,'OP','OPT-IN','WB','WEB','1/4/2015 8:02:00'),
(2,'OP','OPT-IN','WB','WEB','2/1/2015 07:22:00'),
(2,'US','UNSUBSCRIBE','EM','EMAIL','3/2/2015 09:32:00'),
(2,'US','UNSUBSCRIBE','ESP','SERVICE PROVIDER','3/2/2015 09:55:00'),
(2,'US','UNSUBSCRIBE','WB','WEB','3/2/2015 10:15:00')
;with dates as
(
select
email_id,
[OP] as [OptIn_Dttm],
[US] as [Unsub_Dttm]
from
(
select
email_id,
status_cd,
source_dttm
from #history
) as src
pivot (min(source_dttm) for status_cd in ([OP],[US])) as piv
)
select
e.pk_id as email_id,
e.email_address,
e.optin_flag,
/*WANT TO GET THE OPTIN SOURCE HERE*/ /*<-------------*/
d.OptIn_Dttm,
e.unsub_flag,
d.Unsub_Dttm
/*WANT TO GET THE UNSUB SOURCE HERE*/ /*<-------------*/
from #Email e
left join dates d on e.pk_id = d.email_id
How do I increment field of table using varchar. Here an example of what I want to have:
Mark 00001
Mark 00002
Mark 00003
Jaques 00001
Jaques 00002
Jaques 00003
Here is my example It can be useful for other people thanks to those who have helped me a lot thank you
The table is
`CREATE TABLE [dbo].[TAG_Sinistre](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ref_ag] [varchar](7) NULL,
[ref_sinistre] [varchar](7) NULL,
)`
The stored procedure is
create PROC [dbo].[sp_Add_AgSinistre]
#ref_ag varchar (7)
AS BEGIN
declare #id int
DECLARE #ref_sin VARCHAR
SET #id = (SELECT ISNULL(MAX(CAST(ID AS INT)), 0) + 1
FROM TAG_Sinistre where ref_ag=#ref_ag
)
select #ref_sin=right('000000'+CAST(#ref_sin AS VARCHAR(6)),6)
BEGIN
INSERT into TAG_Sinistre(ref_ag,ref_sinistre)
VALUES (#ref_ag,#ref_sin)
Assuming the CompanyName field is UNIQUE, you could get the MAX added value, and increment that?
DECLARE #CurrentSequence INT
SET #CurrentSequence = (SELECT MAX(SequenceId)
FROM TableName WHERE CompanyName = #CompanyName)
INSERT INTO TableName
(CompanyName, SequenceId)
VALUES
(#CompanyName, #CurrentSequence+1)
Your StoredProc would pass in the Company Name as #CompanyName. Obviously, this is a naive approach, and I'm not including what would happen if multiple attempts to update the company would happen simultaneously, but there's no mention of that ion the question.
EDIT: Based on comments
DECLARE #maxSeq INT
SET #maxSeq = (SELECT ISNULL(MAX(CAST(SequenceId AS INT)), 0) + 1 FROM
TableName WHERE CompanyName = #CompanyName)
INSERT INTO TableName
(CompanyName, SequenceId)
VALUES
(#CompanyName, right('000000'+CAST(#maxSeq AS VARCHAR(7)),7))
As I said, I would look to use an INT, and get the UI to present the sequence as you want, instead of casting etc in the DB.
EDIT 2: Added Fiddle
SQL Fiddle
Assuming that your columns always look like those specified above.
DB Trigger (MS-SQL) --> Pseudocode/Untested:
CREATE TRIGGER [dbo].[YourTrigger]
ON [dbo].[YourTable]
INSTEAD OF INSERT
AS
BEGIN
DECLARE #maxVal int
-- PSEUDOCODE!!!
SELECT #maxVal = MAX(CAST(dbo.RegexReplace( '.*?(\d+)', myColumn, '$1') AS INT ))
FROM YourTable
INSERT INTO YourTable
SELECT myColumn + ' ' + #maxVal FROM inserted
END
Use insert now like this:
INSERT INTO YourTable values('Jaques')
I need to do a query between two tables and find non matching fields
table 1 field locations has "my String"
table 2 field locations has "MY string"
they = by text but not by capitalization i need to return a false for this
Having the following data:
DECLARE #TableOne TABLE
(
[ID] TINYINT
,[Value] VARCHAR(12)
)
DECLARE #TableTwo TABLE
(
[ID] TINYINT
,[Value] VARCHAR(12)
)
INSERT INTO #TableOne ([ID], [Value])
VALUES (1,'my String')
INSERT INTO #TableTwo ([ID], [Value])
VALUES (1,'MY String')
You can use set Case Sentitive collation like this:
SELECT [TO].[Value]
,[TW].[Value]
FROM #TableOne [TO]
INNER JOIN #TableTwo [TW]
ON [TO].[ID] = [TW].[ID]
AND [TO].[Value] <> [TW].[Value]
COLLATE Latin1_General_CS_AS
or use HASH functions like this:
SELECT [TO].[Value]
,[TW].[Value]
FROM #TableOne [TO]
INNER JOIN #TableTwo [TW]
ON [TO].[ID] = [TW].[ID]
WHERE HASHBYTES('SHA1', [TO].[Value]) <> HASHBYTES('SHA1', [TW].[Value])
DECLARE #Table1 AS TABLE (FieldName VARCHAR(100))
DECLARE #Table2 AS TABLE (FieldName VARCHAR(100))
INSERT INTO #Table1 (FieldName) VALUES ('MY Location')
INSERT INTO #Table2 (FieldName) VALUES ('My Location')
With a default case insensitive collation order - Matches and returns results
SELECT * FROM #Table1 AS T1
INNER JOIN #Table2 AS T2
ON T1.FieldName = T2.FieldName
With a case sensitive collation order specified. Will not match
SELECT * FROM #Table1 AS T1
INNER JOIN #Table2 AS T2
ON T1.FieldName = T2.FieldName COLLATE Latin1_General_CS_AS_KS_WS
Microsoft article on collation
OrchardCMS developers/users,
I have
public class MyContentPartRecord : ContentPartRecord
{ ... }
I want to change it to
public class MyContentPartRecord : ContentPartVersionRecord
{ ... }
In order to be able to create drafts for this part.
I add to Migraions
SchemaBuilder.AlterTable(
"MyContentPartRecord",
table =>
table
.AddColumn<int>("ContentItemRecord_id")
);
I run the app and the result is on get a content item of MyContentPart it creates an empty published version.
In db for MyContentPartRecord table:
Id [..fields..] ContentItemRecord_Id
657 NULL,.. 67
67 'MYDATA',... NULL
How to create a valid draftable MyContentPart?
UPDATE. I've tried with no success to add:
SchemaBuilder.ExecuteSql(#"
UPDATE MyContentPartRecord
SET ContentItemRecord_id = t2.ContentItemRecord_id
from MyContentPartRecord t1 inner join Orchard_Framework_ContentItemVersionRecord t2 on t1.id= t2.id
");
as it seems that orchard can't work with old records from MyContentPartRecord table as they don't have ContentItemRecord_id set.
You won't be able to do that without a manual SQL script.
The Id means a different thing for those two:
for ContentPartRecord it's a foreign key to an Id of a ContentItemRecord
for ContentPartVersionRecord it's a foreign key to an Id of a ContentItemVersionRecord
So after adding a new column ContentItemRecord_id you need to
first, copy existing data from Id column to ContentItemRecord_id and then
fill Id column with proper ids of the Latest version of each of those items. Version records are kept in Orchard_Framework_ContentItemVersionRecord table.
With the Piotr's help here is a solution. The following to be put in Migrations.cs:
SchemaBuilder.AlterTable(
"MyContentPart",
table =>
table
.AddColumn<int>("ContentItemRecord_id")
);
SchemaBuilder.ExecuteSql(#"
ALTER TABLE MyModuleName_MyContentPart
DROP CONSTRAINT PK__MyModuleName_W__3214EC072C83793F
");
SchemaBuilder.ExecuteSql(#"
INSERT INTO MyModuleName_MyContentPart
(Id, ContentItemRecord_id, Field1, Field2)
SELECT t3.Id AS id, t2.Id AS ContentItemRecord_id, t2.Field1, t2Field2
FROM MyModuleName_MyContentPart AS t2 LEFT OUTER JOIN
Orchard_Framework_ContentItemVersionRecord AS t3 ON t2.Id = t3.ContentItemRecord_id
WHERE (t3.Latest = 1) AND (NOT (t3.Id IS NULL))
");
SchemaBuilder.ExecuteSql(#"
DELETE FROM MyModuleName_MyContentPart
WHERE ContentItemRecord_id is NULL
");
SchemaBuilder.ExecuteSql(#"
ALTER TABLE MyModuleName_MyContentPart
ADD CONSTRAINT PK_MyModuleName_MyContentPart_ID PRIMARY KEY (Id)
");
UPDATE.
The final solution:
SchemaBuilder.AlterTable(
"MyContentPart",
table =>
table
.AddColumn<int>("ContentItemRecord_id")
);
SchemaBuilder.ExecuteSql(#"
ALTER TABLE MyModuleName_MyContentPart
DROP CONSTRAINT PK__MyModule_W__3214EC072C83793F
");
SchemaBuilder.ExecuteSql(#"
INSERT INTO MyModuleName_MyContentPart
(Id, ContentItemRecord_id, Field1)
SELECT V.Id as Id
,T.Id as ContentItemRecord_id
,Field1
FROM [MyModuleName_MyContentPart] T
LEFT OUTER JOIN
Orchard_Framework_ContentItemVersionRecord AS V ON V.ID in
(select top(1) Id
from Orchard_Framework_ContentItemVersionRecord
where ContentItemRecord_id = T.ID
order by latest desc, id desc)
");
SchemaBuilder.ExecuteSql(#"
DELETE FROM MyModuleName_MyContentPart
WHERE ContentItemRecord_id is NULL
");
SchemaBuilder.ExecuteSql(#"
ALTER TABLE MyModuleName_MyContentPart
ADD CONSTRAINT PK_MyModuleName_MyContentPart_ID PRIMARY KEY (Id)
");
}
Here's a more generic solution that can go in your migration.cs file based on #Artjom and #PiotrSzmyd's soltuion. This solution handles the fact that the automatically generated primary key may be named differently for each user of your module. Also the table name may be prefixed if a user has defined a global database prefix (eg. when using multi-tenant).
// Manually add the column that is required for the part to be a ContentPartVersionRecord
SchemaBuilder.AlterTable("MyCustomPartRecord", table => table.AddColumn<int>("ContentItemRecord_id"));
// Get table name
var tablePrefix = String.IsNullOrEmpty(_shellSettings.DataTablePrefix) ? "" : _shellSettings.DataTablePrefix + "_";
var tableName = tablePrefix + "MyModule_MyCustomPartRecord";
// Drop the primary key
SchemaBuilder.ExecuteSql(string.Format(#"
DECLARE #primaryKeyName NVARCHAR(MAX)
SELECT #primaryKeyName = constraint_name
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'Primary Key' and TABLE_NAME = '{0}'
EXEC(N'ALTER TABLE {0} DROP CONSTRAINT ' + #primaryKeyName)
", tableName));
// Migrate IDs to ContentItemRecord_id
SchemaBuilder.ExecuteSql(string.Format(#"
INSERT INTO {0} (Id, ContentItemRecord_id, Category_Id, ItemCode, Name, Description, DisplayOrder, Location, MaintenanceFrequency, MaintenanceFrequencyMultiplier, MaintenanceStartDate, Notes, IsEnabled)
SELECT V.Id as Id, T.Id as ContentItemRecord_id, Category_Id, ItemCode, Name, Description, DisplayOrder, Location, MaintenanceFrequency, MaintenanceFrequencyMultiplier, MaintenanceStartDate, Notes, IsEnabled
FROM {0} T
LEFT OUTER JOIN
{1}Orchard_Framework_ContentItemVersionRecord AS V ON V.ID in
(select top(1) Id
from {1}Orchard_Framework_ContentItemVersionRecord
where ContentItemRecord_id = T.ID
order by latest desc, id desc)
", tableName, tablePrefix));
// Remove old rows (no ContentItemRecord_id value)
SchemaBuilder.ExecuteSql(string.Format(#"
DELETE FROM {0}
WHERE ContentItemRecord_id is NULL
", tableName));
// Re-add the primary key
SchemaBuilder.ExecuteSql(string.Format(#"
ALTER TABLE {0}
ADD CONSTRAINT PK_{0}_Id PRIMARY KEY (Id)
", tableName));