Is the Pre-Deployment script (Script.PreDeployment.sql) the best place to put sql commands that create server level objects (specifically logins in my case)?
I need to create server logins for the database users in the project and this seems the only vaguely logical place to put them as everything else in the project structure (created from reversing our dev db) is database specific. I therefore just wanted to check where others store their server level commands when working with Visual Studio Database Projects.
Many Thanks.
Anything you need prior to deploying your database would be in that script.
In our case, we add logins in the post deployment script. They are not needed when we deploy the database, and we decided to put all the security related commands in the same place.
IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'$(DefaultLogin)')
BEGIN
BEGIN TRY
CREATE LOGIN [$(DefaultLogin)] FROM WINDOWS WITH DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]
END TRY
BEGIN CATCH
-- A try-catch is needed in case a user with a different name is created for the LOGIN specified.
END CATCH
END
GO
IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = N'$(DefaultLogin)')
BEGIN
BEGIN TRY
CREATE USER [$(DefaultLogin)] FOR LOGIN [$(DefaultLogin)] WITH DEFAULT_SCHEMA=[dbo]
-- The db_owner role is added to the current database.
EXEC sp_addrolemember N'db_owner', N'$(DefaultLogin)'
END TRY
BEGIN CATCH
-- A try-catch is needed in case a user with a different name is created for the LOGIN specified.
END CATCH
END
Here is the Pre and Post deployment reference.
Related
We have an Apex application (version 20.1) and our users must be able to change the database schema at runtime via button click (preferably without logging in again).
Currently we are solving this by installing our application multiple times, once per schema.
We recently discovered the function apex_export.get_application. We intend to use this function to bring our frontend under version control (finally!). We would like to deploy our application directly from the exported files. Having a single application, we would not have to mess with the internal component ids from the exported files.
Is it possible to install the application once and change the default schema via Pl/SQL code? Thank you!
I don't think this can be done, but perhaps the following is a reasonable compromise
add all the schemas you need to support to the workspace schema list
Any SQL (and I do mean any) in your app would be prefixed with an application item, eg
Before: select * from my_table
After: select * from &my_schema..my_table
At login time (or when a user selects it) you modify the MY_SCHEMA application item
(I've not tried this...so test/tread carefully)
I attempted to create a workspace in APEX using an existing schema called PEOPLE and it gave the error message "The schema is reserved or restricted". I tried with other existing schemas that I created and they all worked fine.
Technical/Environment details follow:
Database: Oracle 19c EE installed on local machine.
Apex: 19.2 installed as Embedded Gateway on local machine.
Created pluggable database called PDB1.
Created tablespace PEOPLE_TAB using OMF (Oracle Managed Files) syntax.
Created local user PEOPLE in PDB1.
Gave PEOPLE the following roles and privs (I'm aware some are doubled up like RESOURCE role and CREATE SESSION priv):
RESOURCE
UNLIMITED TABLESPACE
SELECT_CATALOG_ROLE
CREATE SESSION
CREATE TABLE
CREATE TYPE
CREATE CLUSTER
CREATE TRIGGER
CREATE PROCEDURE
CREATE SEQUENCE
CREATE VIEW
CREATE DIMENSION
CREATE JOB
CREATE SYNONYM
CREATE DIMENSION
CREATE MATERIALIZED VIEW
I created another user TEST1 in the same tablespace PEOPLE_TAB, with the same privs as PEOPLE and re-created the objects and data. I could successfully create a workspace using this new schema!
Trawled the web, but most articles and posts refer to older versions of APEX, but I still tried the following.
I followed the advice given in the Oracle docs, Application Express Release 19.2 Adminstration Guide section 2.13
The APEX engine schema for APEX 19.2 is APEX_190200. So I unlocked APEX_190200 and logged in (after changing password) to run the checks.
-- Checked if PEOPLE was a restricted schema
SELECT schema FROM APEX_190200.wwv_flow_restricted_schemas order by schema;
PEOPLE is not listed and I assume is not restricted. So I tried to unrestrict PEOPLE anyway as detailed in the docs.
-- ran from APEX_190200
EXEC APEX_INSTANCE_ADMIN.UNRESTRICT_SCHEMA(p_schema => 'PEOPLE');
COMMIT;
Successfully ran but did not resolve the issue.
Looking on the web most of the info was out of date but tried anyway.
-- ran from APEX_190200
EXEC APEX_SITE_ADMIN_PRIVS.UNRESTRICT_SCHEMA(p_schema => 'PEOPLE');
COMMIT;
The above did not run and complained the package didn't exist. I verified that when looking for APEX_SITE_ADMIN_PRIVS in user_objects - it was not there.
Some years ago there was a bug with the function wwv_flow_provision.IS_RESERVED, but I checked this and it ran ok returning FALSE for PEOPLE and TRUE for reserved words like VARCHAR.
It's really thrown me when I can create an identical user (different name) with identical privs, objects and data was created on the same tablespace and it worked fine with an APEX workspace.
Does anyone have any experience of resolving this issue or point me in the right direction?
Thank you.
You are receiving the error because PEOPLE is specified as a restricted schema with an APEX package.
In the installation scripts for APEX 19.2, the file named f4050.sql has a page validation on page 79 (the page that is raising the error) that looks like this:
...
...
...
wwv_flow_api.create_page_validation(
p_id=>wwv_flow_api.id(114752711027135415)
,p_validation_name=>'schema not reserved/restricted'
,p_validation_sequence=>80
,p_validation=>wwv_flow_string.join(wwv_flow_t_varchar2(
'wwv_flow_provision.schema_name_valid(',
' p_schema => :F4050_P79_SCHEMA,',
' p_workspace_name => :F4050_P27_COMPANY);'))
,p_validation_type=>'PLSQL_EXPRESSION'
,p_error_message=>'Schema is reserved or restricted'
,p_when_button_pressed=>wwv_flow_api.id(12559200978895311)
,p_error_display_location=>'INLINE_WITH_FIELD_AND_NOTIFICATION'
);
...
...
...
Then using a procedure block like this, you can determine if the schema name is valid or not:
BEGIN
IF apex_190200.wwv_flow_provision.schema_name_valid (p_schema => 'PEOPLE',
p_workspace_name => 'PEOPLE')
THEN
DBMS_OUTPUT.put_line ('Valid');
ELSE
DBMS_OUTPUT.put_line ('Invalid');
END IF;
END;
/
Then by unwrapping the code in those packages (tools can be easily found online). Within that code, there is a call to another function named WWV_FLOW_PROVISIONING.RESERVED_SCHEMA (P_SCHEMA => P_SCHEMA). Within that function, there is code that looks like this:
IF C_SCHEMA IN (
'HTMLDB_PUBLIC_USER',
'APEX_PUBLIC_USER',
'PUBLIC_USER',
'FLOWS_FILES',
'SCHEDULER',
'PEOPLE') THEN
RETURN TRUE;
END IF;
So without modifying the package WWV_FLOW_PROVISIONING (which I would highly recommend AGAINST), you will not be able to create an APEX workspace with the schema name PEOPLE. This will need to be fixed by Oracle either through a patch to the package or in a newer version of APEX.
Fascinating issue. The restricted schema is hard-coded in APEX provisioning code. It's very much a legacy issue.
We can attempt to fix this in the next release of APEX, but that won't help you now. If you file a Service Request for Oracle Support, I'll make sure you get a fix for this issue (assuming you're using a supported version of APEX).
I've create a SQL Server Database Project and imported my database. I've got a few static data tables that I want to recreate every time it's redeployed, so these get recreated as part of the post deployment script.
To ensure this drops and recreates them I've changed these static data tables to have a build action of 'None' so they are dropped as part of the build and only recreated as part of post deployment steps.
My problem is that I have a view that references these tables. Obviously this shows syntax errors as the tables are no longer part of the build as their build action is 'None'. My workaround was to try and create the view also as part of the post deployment script. I do this with the following code:
:r .\PostDeploymentScripts\Views\myView.sql
The actual script looks like this:
CREATE VIEW [CompTotalByType] AS
SELECT
c.Id,
t.id AS TypeId,
SUM(c.total) AS CompTotal,
FROM CompNumber c
INNER JOIN Type t
ON t.ProdId = c.ProdId
GROUP BY
c.Id,
t.id
However, now I get a syntax error under 'CREATE VIEW' as follows:
Severity Code Description Project File Line Suppression State
Error SQL72007: The syntax check failed 'Incorrect syntax near CREATE.' in the batch near:
'CREATE VIEW [CompTotalByType] AS' ....path name....
However, when I put this code into SSMS it has no syntax errors. What's causing this?
I found the answer here: SQL72007: The syntax check failed 'Unexpected end of file occurred.' in batch near :
It was the second answer that said you needed to add a 'GO' to the previous script. This makes sense as the CREATE VIEW needs to be in its own batch. So I added a 'GO' to the bottom of my previous script before creating the view and that fixed it.
How many static tables are you trying to recreate? I have a similar situation, but what I do instead is create 'MERGE' scripts using a stored procedure on Github called sp_generate_merge. Then I simply include those scripts within the project under a 'Scripts' folder and call them within the post-deployment script. That way you don't have to drop/create them, and your view and tables can be included in the build.
However, if you'd like to keep it the same - it seems that the other user is correct in saying that you need to add 'GO' before 'CREATE VIEW'.
I am trying to add a role membership with my SSDT database project.
EXECUTE sp_addrolemember #rolename = N'<RoleName>', #membername = N'<Domain>\svc.data'
I get the following error:
SQL71501: Role Membership: <unnamed> has an unresolved reference to object [<Domain>\svc.data]
The user and logins are defined and if I switch the code to another user ie:
EXECUTE sp_addrolemember #rolename = N'<RoleName>', #membername = N'<Domain>\svc.data2'
It works perfectly.
I have reimported the schema from the live database (the live database works fine) and I get the same error.
I just found out what you can try. But make sure you have latest SSDT power tools installed:
1) Create a folder like Security
2) Right-click, then Add -> New Item
3) Under SQL Server -> Security
There is a Server Role type file and Server Role Membership.
Let me know if that helps.
I used that to create the Database Role, moved out the scripts out of the post-deploy and it all worked well. I was also granting the permissions in the same file, just had to use GO separator after each line.
I am trying to migrate an access database from 2000 to 20007 version. I have two .mdb files one used as a front end and the other containing only the back end tables. I performed all the necessary initialization for the migration like export of table, extension with .accd, etc.. But when i execute the following code , i get an error " Microsoft office cannot find the input table or query . Check spelling and so".
set Db=currentDb
SQLText ='some sql query'
Db.OpenRecordset(SQLText, dbOpenDynaset)
When i tried to output the value of Db with a msgbox (MSgbox Db), it shows the message "ABC, type mismatch", where ABC is the function name. But, Msgbox Db.name showing the correct database name. But, the same code has been running fine on the older version.
Please help me on this
Okay, you do not have to "migrate" to a different version persay. You only have to import everything from an MDB to ACCDB file. That is all. Scratch whatever you have done, start afresh.
Create a new "empty" accdb file, then using the options under
External Data-> Import/Link From Access. Select the Front End Access
file. Use the Option IMPORT Forms, Report etc., select all Forms, Reports, Queries, Mods then click OK. This
will import all objects.
Create a new "empty" accdb file, then using the options under
External Data-> Import/Link From Access. Select the Back End Access file. Use the Option IMPORT Forms, Report etc., select all tables and click OK. This will import all the tables over to the new file.
Now open up your new "front end" (the one with accdb extension). Under External Data -> Import/Link. Select the new "back end" (the one with the accdb extension). Use the Link to the Data Source option. Then select all tables and click OK.
Now perform a Compact & Repair, follow it with a Compile of the VBA code.
The whole strategy will fail if you have a backend DB in a different platform like SQL or Oracle.