Toad for Oracle, Mysql, Sql server

Το καλύτερο εργαλείο για την διαχείριση των βάσεων. Πλέον κάτω από την ομπρέλα της Dell.

Ανοίξτε λογαριασμό στο site υποστήριξης της ORACLE(MOS-Metalink).

Η Oracle προσφέρει support και χρήσιμες πληροφορίες σε προβλήματα και bugs μέσω του συγκεκριμένου site.

Μπορείτε από το eDelivery της Oracle να κατεβάσετε Μysql και Oracle λογισμικό

Mysql μια open source βάση με support πλέον επι πληρωμή, από την Oracle.

Το support της microsoft για όλα τα προιόντα της

Χρήσιμες πληροφορίες-guides που αφορούν τόσο προβλήματα όσο και τρόπους εγκατάστασης του database λογισμικού.

Oracle Documentation

Εδώ υπάρχει το επίσημο documentation της Oracle.

Πέμπτη 9 Μαρτίου 2023

Εγκατάσταση Microsoft SQL Server 2019

Σε αυτό το άρθρο θα αναλύσουμε πως πρέπει να γίνεται μία καινούργια εγκατάσταση SQL Server βήμα βήμα. Συγκεκριμένα θα δούμε το setup για SQL Server 2019. Επίσης θα δούμε τι απαιτείται να έχουμε κάνει πριν ξεκινήσουμε την εγκατάσταση και τι πρέπει να προσέξουμε ώστε να έχουμε όσο το δυνατόν μεγαλύτερη ασφάλεια και απόδοση.

Προαπαιτούμενα

Θα πρέπει να κατεβάσουμε το setup για την εγκατάσταση του SQL Server 2019. Tο βρίσκουμε απευθείας από την Microsoft εδώ.

Για την εγκατάσταση θα χρειαστούμε έναν local admin λογαριασμό με το οποίον θα συνδεθούμε πριν τρέξουμε το setup.

Ως minimum θα πρέπει να έχει τα παρακάτω δικαιώματα:

  • Act as part of the operating system
  • Backup Files & Directories
  • Debug Programs
  • Manage Auditing & Security Log

Για να σηκώσουμε τα Database Engine και Agent services θα χρειαστούμε Active Directory Domain Service Account ή Managed Service Account με τα παρακάτω δικαιώματα:
  • Act as part of the operating system
  • Lock Pages in Memory
  • Perform Volume Maintenance Tasks
  • Bypass Traverse Checking
  • Replace A Process Level Token
  • Adjust Memory Quotas For A Process


Οι δίσκοι θα πρέπει να είναι χωρισμένοι όπως παρακάτω:

  • Στο C drive θα είναι η εγκατάσταση εκτός του λειτουργικού και των binaries του SQL Server.
  • Στο drive θα έχουμε τα datafiles των user databases και αν δεν έχουμε ξεχωριστό δίσκο για τα backups μπορούμε να τα βάζουμε και αυτά σε έναν φάκελο εκεί (συνήθως τα backups τα πέρνουμε σε backup server οπότε δεν χρειαζόμαστε πάντα ξεχωριστό δίσκο στο ίδιο το μηχάνημα).
  • Στο drive θα έχουμε τα transaction log files.
  • Στο drive θα έχουμε τα αρχεία των system databases (master, msdb, model).
  • Στο drive θα έχουμε τα αρχεία της system database TempDB που γίνεται recreate κάθε φορά που ξεκινάει το SQL Server instance.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
1

Η εγκατάσταση

Ξεκινώντας το setup θα πάμε στην καρτέλα Installation και θα επιλέξουμε την πρώτη επίλογή New SQL Server stand-alone installation or add features to an existing installation.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
2

Στην επόμενη οθόνη περιμένουμε ότι ειναι οκ οι έλεγχοι και πατάμε ΟΚ.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
3

Στην επόμενη οθόνη επιλέγουμε την πρώτη επιλογή Perform a new installation of SQL Server 2019, η δεύτερη είναι αν θέλουμε να προσθέσουμε κάποιο feature σε προηγούμενη εγκατάσταση π.χ Polybase.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
4

Στην επόμενη οθόνη διαλέγουμε την έκδοση που θα κάνουμε εγκατάσταση, για το παράδειγμα θα επιλέξω Developer που είναι δωρεάν για δοκιμαστικούς σκοπούς. Ανάλογα με την έκδοση που κάνουμε εγκατάσταση υπάρχει διαφορετικό κόστος και είναι ενεργοποιημένα διαφορετικά features. Για παραγωγική χρήση δωρεάν είναι μόνο η έκδοση Express η οποία έχει αρκετούς περιορισμούς.

Τις διαφορές ανά έκδοση μπορούμε να τις διαβάσουμε αναλυτικά εδώ.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
5

Στην επόμενη καρτέλα επιλέγουμε τα Database Engine Services. Τα άλλα feature είναι προαιρετικά.

Το instance root directory ορίζει που θα γίνουν εγκατάσταση οι system databases, εκεί τις ορίζουμε ξεχωριστό δίσκο π.χ S:\systemdb\:

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
6

Στη συνέχεια επιλέγουμε αν θα χρησιμοποιήσουμε το default instance και θα κάνουμε connect με το servername ή θα χρησιμοποιήσουμε named instance και θα κάνουμε connect με servername\instancename. Το αφήνουμε στο default.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
7

Στην επόμενη οθόνη ορίζουμε τα service accounts που θα σηκώνουν το service του Database Engine και του Agent (που τρέχει τα jobs). Εκεί θα πρέπει να χρησιμοποιήσουμε το service account που φτιάξαμε στα προαπαιτούμενα. Έπειτα βάζουμε το startup type σε Automatic ώστε τα services να σηκώνονται μόνα τους σε περίπτωση π.χ. restart του μηχανήματος.

*Σε περίπτωση που δεν μας έχουν φτιάξει ακόμα το service account και αφήσουμε το local default επιλέγουμε το Grant Perform Volume Maintenance Task.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
8

Στην δεύτερο tab με το Collation βάζουμε το Greek_CI_AS (το default encoding που θα έχουν οι βάσεις). Για να επιλεγεί αυτό επιλέγουμε CustomizeGreek και OK.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
9

Στην επόμενη οθόνη στην καρτέλα Server Configuration ορίζουμε πως θα κάνουμε login στο instance. Επιλέγουμε add current user ώστε ο χρήστης με τον οποίον κάνουμε το install να είναι super admin. Επίσης μπορούμε να επιλέξουμε mixed mode ώστε να προσθέσουμε και ένα sql login (sa) που θα είναι super admin .

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
10

Στην καρτέλα Data Directories ορίζουμε σε ποιόν δίσκο που θα αποθηκεύεται το κάθε τι ως default. Στο πρώτο πεδίο το root folder όλων το path (από την στιγμή που το καθένα θα είναι σε διαφορετικό δίσκο δεν έχει σημασία), στο δεύτερο που θα είναι τα database files των user databases, στο τρίτο που θα είναι transaction log files των user databases και στο τελευταίο ποιο θα είναι το location για όταν κάνουμε backup.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
11

Στην καρτέλα TempDB κάνουμε remove ότι μπορεί να έχει και Add το path με τον δίσκο που θα φτιάχνετε η tempDB, στην περίπτωση μας στο drive T. Βάζουμε και το αντίστοιχο path για το transaction log file της tempDB.

Από default βλέπουμε ότι έχει επιλέξει να φτιάξει 8 datafiles για την tempDB, δεν χρειάζεται να το πειράξουμε.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
12

Στη καρτέλα MaxDOP ορίζουμε το μέγιστο βαθμό παραλληλίας σε cpu logical cores ενός query. Στον SQL Server 2019 μας προτείνει μόνο του, π.χ με 8 logical cores μας προτείνει MaxDOP 8. Αν όμως στο ίδιο μηχάνημα έχουμε κάνει εγκατάσταση και άλλο instance δεν θα θέλαμε να έχει την δυνατότητα να κάνει χρήση 8 logical cores και ίσως είναι καλύτερο το 4. Επίσης θα πρέπει να θυμόμαστε ότι αν δώσουμε παραπάνω logical cores στο μηχάνημα δεν θα χρησιμοποιήσει ποτέ παραπάνω από 4 οπότε αν θέλουμε χωρίς να αλλάξουμε το setting να χρησιμοποιεί μέχρι όσα logical cores έχει θα πρέπει να το ορίσουμε ως 0.

Αναλυτικά τι τιμή προτείνει η Microsoft ανά περίπτωση μπορούμε να το δούμε εδώ.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
13

Στη καρτέλα Memory ορίζουμε το Max Server Memory (RAM) που θα κάνει χρήση το SQL Server instance. Ένα instance όταν ξεκινάει καταλαμβάνει χώρο από την μνήμη και όταν χρειαστεί καταλαμβάνει περισσότερο το οποίο θα το αποδεσμεύση μόνο όταν κάνουμε restart το instance.

Aφήνουμε πάντα τουλάχιστον 4 GB ελεύθερα για το λειτουργικό σύστημα.

Στο παράδειγμα έχουμε 16 GB RAM και προτείνει 12 GB. Φυσικά αν έχουμε πολλαπλά instances θα πρέπει το 12 αυτό να το χωρίσουμε ανάλογα. Επίσης ορίζουμε 1024 MB να καταλαμβάνει εξαρχής αυτή τη μνήμη το instance με το που ξεκινήσει (Min Server Memory).

*Για να αποδεχθεί τις τιμές που βάλαμε θα πρέπει να επιλέξουμε και το checkbox.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
14

Έπειτα αφού βεβαιωθούμε από το Summary ότι δεν ξεχάσαμε κάτι προχωράμε στο Install.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
15

Για να συνδεθούμε τώρα στο SQL Server Instance μπορούμε να το κάνουμε πέρα από το Command Prompt με την χρήση του SQL Server Management Studio (DBA oriented) ή με το Azure Data Studio (Developer/Analysts oriented).

Patching με την τελευταία αναβάθμιση

Δεν τελειώσαμε όμως εδώ. Θα πρέπει να εγκαταστήσουμε το latest Cumulative Update που διορθώνει ότι bug και ότι security risk έχει προκύψει (επίσης μπορεί να προσθέσει και καινούργια features) .

Μπορούμε να κατεβάσουμε απευθείας απο την Microsoft το latest για τον SQL Server 2019 από εδώ.

Η διαδικασία είναι πολύ απλή με έναν next next Wizard.

Πως συνδεόμαστε απομακρυσμένα

Τελειώσαμε την εγκατάσταση όμως θέλουμε να συνδεθούμε.

Για να μπορούμε να συνδεθούμε δικτυακά από άλλον υπολογιστή, πέρα από φυσικά θα πρέπει να έχουμε ανοίξει στο firewall τις πόρτες 1433/1434 που είναι οι default.

Επίσης θα πρέπει να πάμε στο εργαλείο Sql Server Configuration Manager που έγινε εγκατάσταση μαζί με τον SQL Server.

Να πάμε στην καρτέλα Protocols for … κάτω από το SQL Server Network Configuration. Εκεί επιλέγουμε το TCP/IP και στην καρτέλα Protocol στο Enabled βάζουμε Yes (αν δεν είναι ήδη) .

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
16

Security through obscurity

Όπως είπαμε πριν η default πόρτα του SQL Server είναι 1433. Μπορούμε όμως να την αλλάξουμε ώστε να μην μπορεί να συνδεθεί κάποιος που απλά βάζει στο connection το servername και να χρειάζεται το servername και μια πόρτα που δεν θα ξέρει ποια είναι. π.χ servername,1833.

Για να κάνουμε αυτή την αλλαγή στο εργαλείο Sql Server Configuration Manager που είδαμε πριν. Πάμε στην καρτέλα Protocols for … κάτω από το SQL Server Network Configuration. Εκεί επιλέγουμε το TCP/IP και στην καρτέλα IP Addresses σε όλα τα πεδία TCP Port ορίζουμε την πόρτα που θέλουμε.

*Δεν ξεχνάμε να ανοίξουμε αυτή την πόρτα και στο firewall.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
17

Για να ισχύσουν αυτές οι αλλαγές πρέπει να πάμε στην καρτέλα SQL Server Services να βρούμε το service του Database Engine και να κάνουμε δεξί κλικ Restart.

Πώς κάνουμε σωστά μία εγκατάσταση SQL Server
18

Some more Performance Tweaks Recommendations

Πέρα από ότι επιλογές κάναμε κατά την εγκατάσταση με το γραφικό, για την καλύτερη δυνατή απόδοση προτείνετε να πειράξουμε με T-SQL άλλες δύο παραμέτρους.

Η μία είναι το cost threshold for parallelism που ορίζει από πόσο “κόστος”* και πάνω επιτρέπει ένα query να ανοίξει παραλληλία. Όταν η τιμή είναι χαμηλή, ο SQL Server δημιουργεί πλάνο για παράλληλη εκτέλεση και σε “ελαφριά” queries. Αυτό μπορεί να έχει σαν αποτέλεσμα το ένα thread να περιμένει το άλλο να τελειώσει ώστε να επιστρέψει το αποτέλεσμα του query. Αυτή τη καθυστέρηση την βλέπουμε ως CXPACKET wait type. Για αυτό προτείνετε να αλλάξει η τιμή από 5 που είναι το default σε 50.

*Ως “κόστος” είναι τα δευτερόλεπτα που εκτιμάται ότι θα έκανε το query αν έτρεχε σειριακά χωρίς παραλληλία, όχι όμως στον δικό μας Server αλλά σε κάποιο παλιό μηχάνημα που είχε ορίσει η Microsoft τότε.

Επίσης την παράμετρο blocked process threshold που ορίζει τι διάρκειας blocking θα καταγράφονται από alerts, profiler και extended events που αφορούν το blocking. Ορίζοντας ως 10 θα καταγράφει μόνο blockings που είχανε διάρκεια πάνω από 10 δευτερόλεπτα. Το χρειαζόμαστε αν θέλουμε π.χ. να καταγράφουμε τα blockings όπως έχουμε δει στο άρθρο εδώ.

Για εφαρμόσουμε αυτές τις αλλαγές, τρέχουμε σε ένα query window στο instance τα παρακάτω:

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE WITH OVERRIDE;
EXEC sp_configure 'cost threshold for parallelism', 50;
RECONFIGURE WITH OVERRIDE;
EXEC sp_configure 'blocked process threshold (s)', 10;
RECONFIGURE WITH OVERRIDE;

Bonus Script (Για Backup / Index Maintenance / Database Integrity Check SQL Server Agent Jobs)

Με το παρακάτω script που έχω φτιάξει, με μόνο ένα κλικ, κάνει εγκατάσταση το MaintenanceSolution του Ola Hallengren μαζί με έτοιμα παραμετροποιημένα jobs για Backup ,Database Integrity και Index Optimize με τις βέλτιστες παραμέτρους και χρονοδιάγραμμα.

Τα Backup jobs δημιουργούνται disabled καθώς μπορεί να έχουμε άλλη λύση για backup με 3rd party tool. Επίσης κάνει έλεγχο για Availability Group ώστε να τρέχουν μόνο αν είναι η Preffered Backup Replica (για backup / database integrity) και αν είναι Primary Replica (για Index Optimize).

Το μόνο που χρειάζεται να κάνουμε, είναι να εκτελέσουμε το παρακάτω script στο κάθε SQL Server Instance:

Πηγές:

Τετάρτη 1 Φεβρουαρίου 2017

Backup όλων των αντικειμένων μιάς βάσης ενός Microsoft Sql Server (ddl)

Στο άρθρο αυτό θα μιλήσουμε για το πως μπορεί ένας χρήστης να κάνει export το schema μιας βάσης ενός microsoft sql server με την βοήθεια powershell scripting. Πολλές φορές θέλουμε να παίρνουμε το schema μιας βάσης για λόγους versioning και θα θέλαμε αυτό να γίνεται τακτικά και αυτόματα με καποίο job ή script. Λοιπόν αυτό μπορεί να φαίνεται και να είναι εύκολο για μια βάση Oracle (χρήση export εργαλείου) αλλά για έναν Microsoft Sql Server τα πράγματα δεν είναι τόσο απλά.

Για να μπορέσει κάποιος να φτιάξει μια αυτόματη διαδιακασία που θα κάνει export το schema της βάσης καθημερινά θα πρέπει εν ολίγης να κάνει reverse engineering στο εργαλείο που χρησιμοποιεί το management studio. Έφαγα πολλές ανθρωποώρες για να καταλήξω στην δημιουργία κατάλληλου powershell script που να μπορεί να κάνει χρήση του Microsoft smo scripter και να παράγει σε διάφορα αρχεία .sql το σχήμα της βάσης. Για να είμαι σίγουρος ότι προχωράω σωστά χρησιμοποίησα ένα πολύ χρήσιμο εργαλείο που σύγκρινε το σχήμα του script με το σχήμα της βάσης από όπου το πήρα (το σχήμα που εβγαλά το έριχνα σε μια τεστ βάση για να κάνω την σύγκριση). Το εργαλείο είναι το SQL Examiner  και εικόνα του ακολουθεί.


Τελικά μετά απο πολύ δουλεία και ψάξιμο κατέληξα στο παρακάτω Powershell script το οποίο το κοινοποιώ σε όποιο θέλει να κάνει κάτι αντίστοιχο. Ελπίζω να σώσω πολλές ανθρωποώρες δουλειάς απο κάποιον και να σας φανεί χρήσιμο. Χρήσιμες συμβουλές είναι ότι αν θέλει καποιός να φέρει σε ένα DR περιβάλλον όλη την βάση θα πρέπει να τρέξει τα scripts με την εξής σειρά:
1. users, 2. Roles, 3. Schemas, 4. Database Triggers, 5. User Defined Data Types, 6. Defaults, 7. Tables, 8. Tables Trigger, 9. Functions, 10. Views, 11. Store Procedures, 12. Rules, 13. Synonyms, 14. Xml Schema, 15. CLR assemblies.

Παρακάτω ακολουθεί το powershell script που κάνει export ολο το schema. To Script αυτό μπορεί να τρέχει σε  έτσι όπωσ φαίνεται στην πρώτη γραμμή και να οριστεί ένα schedule task που να το καλεί όταν κάποιος θέλει αν το καλέσει:

# Usage:  powershell ExportSchema.ps1 "SERVERNAME" "DATABASE" "C:\<YourOutputPath>"


# Start Script
Set-ExecutionPolicy RemoteSigned

# Set-ExecutionPolicy -ExecutionPolicy:Unrestricted -Scope:LocalMachine
function GenerateDBScript([string]$serverName, [string]$dbname, [string]$scriptpath)
{
  [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
  [System.Reflection.Assembly]::LoadWithPartialName("System.Data") | Out-Null
  $srv = new-object "Microsoft.SqlServer.Management.SMO.Server" $serverName
  $srv.SetDefaultInitFields([Microsoft.SqlServer.Management.SMO.View], "IsSystemObject")
  $db = New-Object "Microsoft.SqlServer.Management.SMO.Database"
  $db = $srv.Databases[$dbname]
  $scr = New-Object "Microsoft.SqlServer.Management.Smo.Scripter"
  $deptype = New-Object "Microsoft.SqlServer.Management.Smo.DependencyType"
  $scr.Server = $srv
  $options = New-Object "Microsoft.SqlServer.Management.SMO.ScriptingOptions"
  $options.AllowSystemObjects = $true
  $options.IncludeDatabaseContext = $true
  $options.IncludeIfNotExists = $true
  $options.ClusteredIndexes = $true
  $options.Default = $true
  $options.DriAll = $true
  $options.Indexes = $true
  $options.Triggers = $true
  $options.NonClusteredIndexes = $true
  $options.IncludeHeaders = $false
  $options.ToFileOnly = $true
  $options.AppendToFile = $true
  $options.ScriptDrops = $false
  $options.Permissions = $true
  $options.WithDependencies = $true
  $options.ExtendedProperties =$true
  #$options.Logins=$true
  #$scr."Object-Level Permissions" = $true
  #$scr.Owner = $true
  $db_role = New-Object "Microsoft.SqlServer.Management.SMO.DatabaseRole"
  $db2 = $srv.Databases.Item($dbname)


  # Set options for SMO.Scripter
  $scr.Options = $options
  
  
  #pairnw tin hmeromhnia kai thn vazw sto arxeio
  $a = Get-Date
  $day=$a.Day
  $month=$a.Month
  $year=$a.Year


 #=============
 # ASSEMBLY
 #=============
  $DBAssemblies  = $db.assemblies # where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_db_assemblies.sql"
  New-Item $options.FileName -type file -force | Out-Null
  
  Foreach ($db_assembly in $DBAssemblies )
  {
    $DBAssemblies | foreach {$_.Script()+ "GO"} | Out-File $($options.FileName) 
   
  }






  #=============
 # Synonyms
 #=============
  $DBSynonyms  = $db.Synonyms # where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_db_rules.sql"
  New-Item $options.FileName -type file -force | Out-Null
  
  Foreach ($db_synonym in $DBSynonyms )
  {
    $DBSynonyms | foreach {$_.Script()+ "GO"} | Out-File $($options.FileName) 
   
  }



 #=============
  # Table Triggers
  #=============
  $options.FileName = $scriptpath + "\$($dbname)_table_triggers.sql"
  New-Item $options.FileName -type file -force | Out-Null
  Foreach ($tb in $db.Tables)
  {     
    if($tb.triggers -ne $null)
    {
      foreach ($trigger in $tb.triggers)
      {
     $tb.triggers| foreach {$_.Script()+ "GO"} | Out-File -Append $($options.FileName) 
        #$scr.Script($trigger)
      }
    }
  } 


 #=============
 # Users
 #=============
  $DBUsers = $db.Users # where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_db_users.sql"
  New-Item $options.FileName -type file -force | Out-Null
  
  Foreach ($db_users in $DBUsers)
  {
    $DBUsers | foreach {$_.Script()+ "GO"} | Out-File $($options.FileName) 
   
  }


  #=============
 # Rules
 #=============
  $DBRules  = $db.Rules # where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_db_rules.sql"
  New-Item $options.FileName -type file -force | Out-Null
  
  Foreach ($db_rule in $DBRules )
  {
    $DBRules  | foreach {$_.Script()+ "GO"} | Out-File $($options.FileName) 
   
  }





 #=============
 # DEfaults
 #=============
  $DBDefaults = $db.Defaults # where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_db_defaults.sql"
  New-Item $options.FileName -type file -force | Out-Null
  
  Foreach ($db_default in $DBDefaults)
  {
    $DBDefaults | foreach {$_.Script()+ "GO"} | Out-File $($options.FileName) 
   
  }


 #=============
 # UserDefinedDataType
 #=============
  $DBtypes = $db.UserDefinedDataTypes # where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_db_types.sql"
  New-Item $options.FileName -type file -force | Out-Null
  
  Foreach ($db_type in $DBtypes)
  {
    $DBtypes| foreach {$_.Script()+ "GO"} | Out-File $($options.FileName) 
   
  }




 #=============
 # DB Schemas
 #=============
  $DBSchemas = $db.schemas # where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_db_schemas.sql"
  New-Item $options.FileName -type file -force | Out-Null
  
  Foreach ($db_schemas in $DBSchemas)
  {
    $DBSchemas| foreach {$_.Script()+ "GO"} | Out-File $($options.FileName) 
   
  }

 #=============
 # DB Roles
 #=============
  $DBRoles = $db.Roles # where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_db_roles.sql"
  New-Item $options.FileName -type file -force | Out-Null
  
  Foreach ($db_role in $DBRoles)
  {
    $DBRoles| foreach {$_.Script()+ "GO"} | Out-File $($options.FileName) 
   
  }
  
  
  #=============
  # Tables
  #=============
  $options.FileName = $scriptpath + "\$($dbname)_tables.sql"
  New-Item $options.FileName -type file -force | Out-Null
  Foreach ($tb in $db.Tables)
  {
   If ($tb.IsSystemObject -eq $FALSE)
   {
    $smoObjects = New-Object Microsoft.SqlServer.Management.Smo.UrnCollection
    $smoObjects.Add($tb.Urn)
    $scr.Script($smoObjects)
   }
  }
  

  

  #=============
  # Views
  #=============
  $options.FileName = $scriptpath + "\$($dbname)_views.sql"
  New-Item $options.FileName -type file -force | Out-Null
  $views = $db.Views | where {$_.IsSystemObject -eq $false}
  Foreach ($view in $views)
  {
    if ($views -ne $null)
    {
     $scr.Script($view)
   }
  }
  
   

  #=============
  # StoredProcedures
  #=============
  $StoredProcedures = $db.StoredProcedures | where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_stored_procs.sql"
  New-Item $options.FileName -type file -force | Out-Null
  Foreach ($StoredProcedure in $StoredProcedures)
  {
    if ($StoredProcedures -ne $null)
    {   
     $scr.Script($StoredProcedure)
   }
  } 

  #=============
  # Functions
  #=============
  $UserDefinedFunctions = $db.UserDefinedFunctions | where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_functions.sql"
  New-Item $options.FileName -type file -force | Out-Null
  Foreach ($function in $UserDefinedFunctions)
  {
    if ($UserDefinedFunctions -ne $null)
    {
     $scr.Script($function)
   }
  } 

  #=============
  # DBTriggers
  #=============
  $DBTriggers = $db.Triggers #| where {$_.IsSystemObject -eq $false}
  $options.FileName = $scriptpath + "\$($dbname)_db_triggers.sql"
  New-Item $options.FileName -type file -force | Out-Null
  foreach ($trigger in $DBTriggers)
  {
    if ($DBTriggers -ne $null)
    {
      #$scr.Script($DBTriggers)
 $DBTriggers| foreach {$_.Script()+ "GO"} | Out-File $($options.FileName) 
    }
  }


}

#=============
# Execute
#=============
$scrap = "-+- Exporting by exportschema.ps1 for " + $args[0] + " " + $args[0] + " " + $args[1] + " " + $args[2]
Write-Output $scrap
GenerateDBScript $args[0] $args[1] $args[2]